<!-- 任务详情页面 童晓白 2025-07-28 -->
<template>
  <scroll-view 
    scroll-y="true" 
    :refresher-enabled="true"
    :refresher-triggered="refreshing"
    :scroll-into-view="scrollIntoView"
    @refresherrefresh="onRefresh"
    class="scroll-container"
  >
    <view v-if="loading" class="loading"><text>加载中...</text></view>
    <view v-else-if="error" class="error"><text>{{ error }}</text></view>
    <view v-else>
      <!-- 头部卡片 -->
      <view class="task-header">
        <image :src="getAvatarUrl(task?.userAvatar)" mode="aspectFill" class="user-avatar" @error="handleTaskAvatarError" />
        <view class="header-main">
          <view class="header-title-row">
            <text class="task-title">{{ taskData?.title }}</text>
            <view class="status-tag"><text>{{ getStatusText(taskData?.status) }}</text></view>
          </view>
          <view class="task-publisher">发布者：{{ taskData?.userName || '未知用户' }} ({{ taskData?.orgName || '未知企业' }})</view>
          <view class="task-time">发布时间：{{ taskData?.publishTime }}</view>
          <view class="task-deadline">截止日期：{{ taskData?.deadline }}</view>
        </view>
      </view>
      <view class="task-body">
        <view class="task-info-row">
          <text class="task-info-label">任务描述:</text>
          <text class="task-info-value">{{ taskData?.description }}</text>
        </view>
        <view class="task-info-row">
          <text class="task-info-label">悬赏金额:</text>
          <text class="task-info-value">{{ formatNumber(taskData?.reward) }} 元</text>
        </view>
        <view class="task-info-row">
          <text class="task-info-label">当前支付:</text>
          <text class="task-info-value">{{ formatNumber(taskData?.currentPaid) }} 元</text>
        </view>
        <view class="task-info-row">
          <text class="task-info-label">任务状态:</text>
          <text class="task-info-value">{{ getStatusText(taskData?.status) }}</text>
        </view>
        <!-- 挑战者信息显示 -->
        <view v-if="taskData?.teamId && (taskData?.status === '2' || taskData?.status === '3')" class="task-info-row">
          <text class="task-info-label">挑战者:</text>
          <text class="task-info-value">
            团队ID {{ formatNumber(taskData?.teamId) }}
          </text>
        </view>
        
        <!-- 任务类型显示 -->
        <view v-if="taskData?.teamId && (taskData?.status === '2' || taskData?.status === '3')" class="task-info-row">
          <text class="task-info-label">任务类型:</text>
          <text class="task-info-value">团队任务</text>
        </view>
        
        <!-- 团队成员信息显示 -->
        <view v-if="teamInfo && teamInfo.members && teamInfo.members.length > 0" class="team-info-section">
          <text class="section-title">团队成员 ({{ teamInfo.members.length }})</text>
          <view class="members-list">
            <view 
              v-for="member in teamInfo.members" 
              :key="member.userId"
              class="member-item"
            >
              <image :src="getUserAvatar(member.userId)" class="member-avatar" @error="handleAvatarError" />
              <view class="member-info">
                <text class="member-name">{{ getUserNickname(member.userId) }}</text>
                <text class="member-role">{{ (member.role === 1 || member.role === '1') ? '队长' : '队员' }}</text>
                <text class="member-status" :class="'status-' + member.status">{{ member.statusText }}</text>
              </view>
              <!-- 任务进行中时的操作按钮 -->
              <view class="member-actions" v-if="!isTaskPublisher && taskData?.status === '2'">
                <!-- 队长可以发起踢人投票（仅任务进行中） -->
                <button 
                  v-if="isTeamLeader && (member.role !== 1 && member.role !== '1') && taskData?.status === '2'"
                  class="vote-remove-btn"
                  @click="initiateRemoveMemberVote(member.userId)"
                >
                  发起踢人投票
                </button>
                <!-- 队长可以转让队长（仅任务进行中） -->
                <button 
                  v-if="isTeamLeader && (member.role !== 1 && member.role !== '1') && taskData?.status === '2'"
                  class="transfer-leader-btn"
                  @click="transferLeadership(member.userId)"
                >
                  转让队长
                </button>
                <!-- 队员可以发起弹劾队长投票（仅任务进行中） -->
                <button 
                  v-if="!isTeamLeader && (member.role === 1 || member.role === '1') && taskData?.status === '2'"
                  class="impeach-leader-btn"
                  @click="initiateImpeachLeaderVote()"
                >
                  弹劾队长
                </button>
                <!-- 队员可以申请退出团队 -->
                <button 
                  v-if="!isTeamLeader && member.userId == currentUserId && taskData?.status === '2'"
                  class="leave-team-btn"
                  @click="leaveTeam"
                >
                  申请退出
                </button>
                
                <!-- 调试信息 -->
                <view style="font-size: 10px; color: red; padding: 8px; background: #fff3cd; border: 1px solid #ffc107; margin: 4px 0;">
                  <text style="font-weight: bold;">调试信息：</text><br/>
                  isTeamLeader: {{ isTeamLeader }}<br/>
                  taskStatus: {{ taskData?.status }}<br/>
                  member.role: {{ member.role }}<br/>
                  member.role原始值: {{ JSON.stringify(member.role) }}<br/>
                  member.userId: {{ member.userId }}<br/>
                  currentUserId: {{ currentUserId }}<br/>
                  isTaskPublisher: {{ isTaskPublisher }}<br/>
                  <view style="margin-top: 4px; font-weight: bold;">
                    条件检查结果：<br/>
                    踢人条件: {{ isTeamLeader && (member.role !== 1 && member.role !== '1') && taskData?.status === '2' }}<br/>
                    转让队长条件: {{ isTeamLeader && (member.role !== 1 && member.role !== '1') && taskData?.status === '2' }}<br/>
                    弹劾队长条件: {{ !isTeamLeader && (member.role === 1 || member.role === '1') && taskData?.status === '2' }}<br/>
                    退出条件: {{ !isTeamLeader && member.userId == currentUserId }}<br/>
                    详细检查: <br/>
                    - isTeamLeader值: {{ isTeamLeader }}<br/>
                    - member.role !== 1: {{ member.role !== 1 }}<br/>
                    - member.role !== '1': {{ member.role !== '1' }}<br/>
                    - taskData?.status === '2': {{ taskData?.status === '2' }}<br/>
                    - member.role === 1: {{ member.role === 1 }}<br/>
                    - member.role === '1': {{ member.role === '1' }}<br/>
                  </view>
                </view>
              </view>
            </view>
          </view>
        </view>
        
        <!-- 团队任务但暂无成员信息 -->
        <view v-else-if="!teamInfo || !teamInfo.members || teamInfo.members.length === 0" class="team-info-section">
          <text class="section-title">团队任务</text>
          <view class="no-team-info">
            <text class="no-team-text">团队信息加载中...</text>
          </view>
        </view>
        
        <!-- 进行中的投票区域 -->
        <view v-if="teamInfo && activeTeamVotes && activeTeamVotes.length > 0" class="active-votes-section-main">
          <text class="section-title">进行中的投票 ({{ activeTeamVotes.length }})</text>
          <view class="votes-list-main">
            <view 
              v-for="vote in activeTeamVotes" 
              :key="vote.voteId"
              class="vote-item-main"
            >
              <view class="vote-header-main">
                <text class="vote-title-main">{{ getVoteTitle(vote) }}</text>
                <view class="vote-type-badge" :class="'type-' + vote.voteType">
                  {{ getVoteTypeText(vote.voteType) }}
                </view>
              </view>
              <view class="vote-content-main">
                <text class="vote-reason-text">原因: {{ vote.reason || '无' }}</text>
                <text class="vote-info-text">发起人: {{ getUserNickname(vote.initiatorId) }}</text>
                <text class="vote-info-text" v-if="vote.targetUserId">目标: {{ getUserNickname(vote.targetUserId) }}</text>
                <text class="vote-deadline-text" v-if="vote.expiresAt">
                  截止时间: {{ formatDateTime(vote.expiresAt) }}
                  <text v-if="vote.remainingSeconds && vote.remainingSeconds > 0" class="countdown-text">
                    (剩余: {{ formatCountdown(vote.remainingSeconds) }})
                  </text>
                </text>
              </view>
              <!-- 投票进度 -->
              <view class="vote-progress-main">
                <view class="vote-results-main">
                  <view class="result-item-main">
                    <text class="result-label-main">同意：</text>
                    <text class="result-count-main approve">{{ vote.approveCount || 0 }}人</text>
                  </view>
                  <view class="result-item-main">
                    <text class="result-label-main">反对：</text>
                    <text class="result-count-main reject">{{ vote.rejectCount || 0 }}人</text>
                  </view>
                  <view class="result-item-main">
                    <text class="result-label-main">未投：</text>
                    <text class="result-count-main pending">{{ vote.pendingCount || 0 }}人</text>
                  </view>
                </view>
                <text class="progress-rule-main">
                  {{ vote.progressType === 'participation' ? 
                    `需要${vote.requiredVotes || 0}人参与投票（共${vote.totalVoters || 0}人，需>50%）` : 
                    getVoteRuleText(vote.voteType, vote.requiredVotes, vote.totalVoters)
                  }}
                </text>
              </view>
              
              <!-- 投票操作区域 -->
              <view class="vote-actions-main" v-if="!vote.hasVoted">
                <!-- 选举投票：候选人选择 -->
                <view v-if="vote.voteType === 3" class="candidate-selection-main">
                  <text class="candidate-label">请选择新队长：</text>
                  <view class="candidates-list">
                    <view 
                      v-for="member in teamInfo.members" 
                      :key="member.userId"
                      class="candidate-item"
                      :class="{ selected: selectedCandidateId === member.userId }"
                      @click="selectCandidate(member.userId)"
                    >
                      <image :src="getUserAvatar(member.userId)" class="candidate-avatar" />
                      <text class="candidate-name">{{ getUserNickname(member.userId) }}</text>
                      <text v-if="selectedCandidateId === member.userId" class="selected-icon">✓</text>
                    </view>
                  </view>
                  <button 
                    class="vote-btn-submit"
                    :disabled="!selectedCandidateId || voteLoading"
                    @click="submitCandidateVote(vote.voteId, selectedCandidateId)"
                  >
                    {{ voteLoading ? '投票中...' : '提交投票' }}
                  </button>
                </view>
                <!-- 普通投票：同意/反对 -->
                <view v-else class="vote-buttons-main">
                  <button 
                    class="vote-btn approve-btn"
                    :disabled="voteLoading"
                    @click="submitVote(vote.voteId, 1)"
                  >
                    {{ voteLoading ? '投票中...' : '同意' }}
                  </button>
                  <button 
                    class="vote-btn reject-btn"
                    :disabled="voteLoading"
                    @click="submitVote(vote.voteId, 2)"
                  >
                    {{ voteLoading ? '投票中...' : '反对' }}
                  </button>
                </view>
              </view>
              <!-- 已投票状态 -->
              <view class="vote-status-main" v-else>
                <text class="voted-status-text">
                  您已投票: {{ getVoteChoiceText(vote.userVote, vote.voteType) }}
                </text>
                <button 
                  @click="withdrawVoteFromTask(vote.voteId)" 
                  class="withdraw-btn-main"
                  :disabled="withdrawLoading"
                >
                  {{ withdrawLoading ? '撤回中...' : '撤回投票' }}
                </button>
              </view>
            </view>
          </view>
        </view>
        
        <!-- 投票记录（历史投票） -->
        <view v-if="teamInfo && voteHistory && voteHistory.length > 0" class="vote-history-section">
          <text class="section-title">投票记录</text>
          <view class="history-list">
            <view 
              v-for="vote in voteHistory" 
              :key="vote.voteId || vote.id"
              class="history-item"
            >
              <view class="history-header">
                <text class="history-title">{{ getVoteTitle(vote) }}</text>
                <text class="history-status" :class="'status-' + (vote.status || vote.voteStatus)">
                  {{ getVoteStatusText(vote.status || vote.voteStatus) }}
                </text>
              </view>
              <view class="history-content">
                <text class="history-info">发起人: {{ getUserNickname(vote.initiatorId) }}</text>
                <text class="history-info" v-if="vote.targetUserId">目标: {{ getUserNickname(vote.targetUserId) }}</text>
                <text class="history-info">原因: {{ vote.reason || '无' }}</text>
                <text class="history-time" v-if="vote.createdAt">
                  发起时间: {{ formatDateTime(vote.createdAt) }}
                </text>
                <text class="history-time" v-if="vote.endedAt">
                  结束时间: {{ formatDateTime(vote.endedAt) }}
                </text>
              </view>
              <!-- 投票详情 -->
              <view class="history-votes" v-if="vote.voteDetails && vote.voteDetails.length > 0">
                <text class="history-votes-title">投票详情：</text>
                <view 
                  v-for="detail in vote.voteDetails" 
                  :key="detail.voterId"
                  class="vote-detail-item"
                >
                  <image :src="getUserAvatar(detail.voterId)" class="detail-avatar" />
                  <text class="detail-name">{{ getUserNickname(detail.voterId) }}</text>
                  <text class="detail-choice" :class="'choice-' + detail.voteChoice">
                    {{ getVoteChoiceDetailText(detail.voteChoice, vote.voteType) }}
                  </text>
                  <text class="detail-reason" v-if="detail.voteReason">理由: {{ detail.voteReason }}</text>
                </view>
              </view>
              <!-- 投票结果 -->
              <view class="history-result">
                <text class="result-summary">
                  结果: 同意{{ vote.approvalVotes || vote.approveCount || 0 }}票，
                  反对{{ vote.rejectionVotes || vote.rejectCount || 0 }}票
                </text>
              </view>
            </view>
          </view>
        </view>
      </view>
      <!-- 进行中时的快捷操作条 -->
      <view v-if="showApplyCompleteBtn || isPublisherAndInProgress" class="quick-actions">
        <button v-if="showApplyCompleteBtn" class="apply-shortcut-btn" @click="goToApplyComplete"><text>去申请完成</text></button>
        <button v-if="isPublisherAndInProgress" class="apply-shortcut-btn" @click="viewApplyCompleteInfo"><text>查看申请完成详情</text></button>
      </view>

      <!-- 任务操作按钮区域 -->
      <view v-if="showTaskActions" class="task-actions">
        <!-- 撤回申请按钮 - 只有申请者可以撤回，且没有待处理的消息 -->
        <button v-if="canCancelApply && !hasPendingMessages" class="cancel-apply-btn" @click="cancelTaskApply">
          <text>撤回申请</text>
        </button>
        
        <!-- 申请取消任务按钮 - 只有进行中任务可以申请取消，且没有待处理的消息 -->
        <button v-if="canRequestCancel && !hasPendingMessages" class="request-cancel-btn" @click="openCancelRequestModal">
          <text>申请取消任务</text>
        </button>
        
        <!-- 修改任务按钮 - 只有发布者可以修改，且任务状态为1或2，修改次数未达上限 -->
        <button v-if="canEditTask" class="edit-task-btn" @click="goToEditTask">
          <text>修改任务</text>
        </button>
        
        <!-- 删除任务按钮 - 只有发布者可以删除，且任务状态为0或1 -->
        <button v-if="canDeleteTask" class="delete-task-btn" @click="deleteTask">
          <text>删除任务</text>
        </button>
        
        <!-- 待处理消息提示 -->
        <view v-if="hasPendingMessages" class="pending-messages">
          <text class="pending-title">有待处理的消息</text>
          <view v-for="msgType in pendingMessageTypes" :key="msgType" class="pending-item">
            <text v-if="msgType === 3">• 任务申请待处理</text>
            <text v-else-if="msgType === 9">• 取消申请待处理</text>
            <text v-else-if="msgType === 4">• 完成申请待处理</text>
          </view>
          <button class="view-messages-btn" @click="goToMessages">
            <text>查看消息</text>
          </button>
        </view>
      </view>

      <!-- 工作记录（在开始/结束按钮之上显示） -->
      <view v-if="showWorkControls" class="work-records">
        <text class="work-section-title">我的工作记录</text>
        <view v-if="workLoading" class="loading"><text>加载中...</text></view>
        <view v-else-if="workError" class="error"><text>{{ workError }}</text></view>
        <view v-else>
          <view v-if="!workTimes || workTimes.length === 0" class="empty-records"><text>暂无记录</text></view>
          <view v-else>
            <view v-for="wt in workTimes" :key="wt.id || wt.workTimeId" class="work-item">
              <view class="work-item-row">
                <text class="work-item-label">开始</text>
                <text class="work-item-value">{{ formatDateTime(wt.startTime || wt.start_at || wt.start) }}</text>
              </view>
              <view class="work-item-row">
                <text class="work-item-label">结束</text>
                <text class="work-item-value">{{ (wt.endTime || wt.end_at || wt.end) ? formatDateTime(wt.endTime || wt.end_at || wt.end) : '进行中' }}</text>
              </view>
            </view>
          </view>
        </view>
      </view>

      <!-- 开始/结束工作按钮（在申请完成之上显示） -->
      <view v-if="showWorkControls" class="work-actions">
        <button 
          class="start-work-btn" 
          :disabled="hasOngoingWork || startWorking"
          @click="startWork"
        ><text>{{ startWorking ? '开始中...' : '开始工作' }}</text></button>
        <button 
          class="end-work-btn" 
          :disabled="!hasOngoingWork || endWorking"
          @click="endWork"
        ><text>{{ endWorking ? '结束中...' : '结束工作' }}</text></button>
      </view>

      <view class="map-container" v-show="!loading && !error">
        <map 
          id="map3D" 
          :longitude="taskData?.longitude" 
          :latitude="taskData?.latitude"
          :markers="mapMarkers"
          class="map"
          :scale="15"
          show-location
          enable-zoom
          enable-scroll
          enable-rotate
        >
          <!-- #ifdef APP-PLUS -->
          <cover-view class="map-wrapper"></cover-view>
          <!-- #endif -->
        </map>
        <button @click="moveToTaskLocation" class="move-to-task-btn"><text>定位到任务位置</text></button>
      </view>
      <view class="task-badges">
        <text class="badge-title">完成任务可获得荣誉</text>
        <view v-if="taskData?.badges && taskData?.badges.length > 0">
          <view v-for="badge in taskData?.badges" :key="badge.id" class="badge">
            <text>{{ getBadgeNameByAssociation(badge.association)}}  Lv{{ formatNumber(badge.level) }}</text>
            <text v-if="badge.contributors && taskData?.status === '3'"><text class="badge-label">贡献者:</text></text>
            <view v-if="badge.contributors && taskData?.status === '3'">
              <view v-for="contributor in badge.contributors" :key="contributor.uid">
                <text>UID: {{ formatNumber(contributor.uid) }} - {{ contributor.role }} - {{ formatPercentage(contributor.percentage) }}%</text>
              </view>
            </view>
            <text v-if="badge.contributors && taskData?.status === '3'"><text class="badge-label">评价:</text> {{ badge.evaluation }}</text>
          </view>
        </view>
        <text v-else>暂无徽章</text>
      </view>
      
      <view v-if="taskData?.status === '1' && taskData?.publisherId !== currentUserId" class="challenge-section">
        <view class="form-group">
          <view class="challenge-content-container">
            <textarea 
              v-model="challengeContent" 
              :maxlength="1000"
              :show-confirm-bar="false"
              :cursor-spacing="20"
              placeholder="请详细描述任务的具体要求、功能需求、技术规格等信息..."
              class="challenge-content"
            ></textarea>
            <view class="character-counter">
              <text>{{ formatCharacterCount(challengeContent.length) }}/1000</text>
            </view>
          </view>
        </view>
          <!-- 申请方式选择 -->
        <view class="application-methods">
          <!-- 现在所有挑战都通过团队实现，默认显示团队角色选择 -->
          
          <!-- 团队角色选择 -->
          <view class="team-role-selection">
            <text class="role-selection-title">选择您的角色</text>
            <view class="role-options">
              <!-- 队长选项 -->
              <view class="role-option" :class="{ 'selected': teamRole === 'leader' }" @click="selectTeamRole('leader')">
                <view class="role-header">
                  <view class="role-icon leader-icon">👑</view>
                  <text class="role-title">我是队长</text>
                  <view class="role-badge" v-if="teamRole === 'leader'">已选择</view>
                </view>
                <text class="role-description">创建团队，邀请队员，管理团队事务</text>
                <view class="role-responsibilities">
                  <text class="responsibility-item">• 创建和管理团队</text>
                  <text class="responsibility-item">• 邀请和移除队员</text>
                  <text class="responsibility-item">• 提交挑战申请</text>
                  <text class="responsibility-item">• 分配团队任务</text>
                </view>
              </view>
              
              <!-- 队员选项 -->
              <view class="role-option" :class="{ 'selected': teamRole === 'member' }" @click="selectTeamRole('member')">
                <view class="role-header">
                  <view class="role-icon member-icon">🤝</view>
                  <text class="role-title">我是队员</text>
                  <view class="role-badge" v-if="teamRole === 'member'">已选择</view>
                </view>
                <text class="role-description">加入现有团队，参与团队协作</text>
                <view class="role-responsibilities">
                  <text class="responsibility-item">• 接受队长邀请</text>
                  <text class="responsibility-item">• 参与团队讨论</text>
                  <text class="responsibility-item">• 完成分配任务</text>
                  <text class="responsibility-item">• 协助团队决策</text>
                </view>
              </view>
            </view>
          </view>
          
          <!-- 组队模式表单 -->
          <view v-if="teamMode || canShowTeamInfo" class="team-application-form">
            <!-- 团队信息 -->
            <view v-if="teamInfo" class="team-info-section">
              <text class="section-title">团队信息</text>
              <view class="team-info-item">
                <text class="info-label">团队名称：</text>
                <view v-if="isTeamLeader && !isTaskPublisher" class="team-name-edit">
                  <input 
                    v-model="editingTeamName" 
                    class="team-name-input" 
                    placeholder="请输入团队名称"
                    maxlength="20"
                    @input="handleTeamNameInput"
                    @focus="handleTeamNameFocus"
                  />
                  <button class="save-name-btn" @click="saveTeamName" :disabled="!editingTeamName.trim()">保存</button>
                </view>
                <view v-else class="team-name-display">
                  <text class="team-name-text">{{ teamInfo.teamName || '临时团队' }}</text>
                  <text v-if="isTaskPublisher" class="role-hint">（任务发布者，仅可查看）</text>
                  <text v-else class="role-hint">（您不是队长，无法修改团队名称）</text>
                </view>
              </view>
              <view class="team-info-item">
                <text class="info-label">团队状态：</text>
                <text class="info-value">{{ getTeamStatusText(teamInfo.status) }}</text>
                <button v-if="teamInfo.status === 2" class="recreate-btn" @click="recreateTeamFromDissolved">
                  重新创建
                </button>
              </view>
            </view>
            
            
            <!-- 进行中的投票显示 -->
            <view v-if="teamInfo && teamInfo.activeVotes && teamInfo.activeVotes.length > 0" class="active-votes-section">
              <text class="section-title">进行中的投票</text>
              <view class="votes-list">
                <view 
                  v-for="vote in teamInfo.activeVotes" 
                  :key="vote.voteId"
                  class="vote-item"
                >
                  <view class="vote-header">
                    <text class="vote-title">{{ vote.voteTitle || (vote.voteType === 1 ? '踢人投票' : (vote.voteType === 2 ? '弹劾投票' : '投票')) }}</text>
                    <text class="vote-type">{{ vote.voteTitle || (vote.voteType === 1 ? '踢人投票' : (vote.voteType === 2 ? '弹劾投票' : '投票')) }}</text>
                  </view>
                  <view class="vote-content">
                    <text class="vote-reason">原因: {{ vote.reason }}</text>
                    <text class="vote-initiator">发起人: {{ getUserNickname(vote.initiatorId) }}</text>
                    <text class="vote-target" v-if="vote.targetUserId">目标: {{ getUserNickname(vote.targetUserId) }}</text>
                  </view>
                  <!-- 投票进度 -->
                  <view class="vote-progress">
                    <text class="progress-text">投票结果</text>
                    <view class="vote-results">
                      <view class="result-item">
                        <text class="result-label">同意：</text>
                        <text class="result-count approve">{{ vote.approveCount || 0 }}人</text>
                      </view>
                      <view class="result-item">
                        <text class="result-label">反对：</text>
                        <text class="result-count reject">{{ vote.rejectCount || 0 }}人</text>
                      </view>
                      <view class="result-item">
                        <text class="result-label">未投：</text>
                        <text class="result-count pending">{{ vote.pendingCount || 0 }}人</text>
                      </view>
                    </view>
                    <text class="progress-rule" style="font-size: 12px; color: #6c757d; margin-top: 4px;">
                      {{ vote.progressType === 'participation' ? 
                        `需要${vote.requiredVotes || 0}人参与投票（共${vote.totalVoters || 0}人，需>50%），候选人需获得超过50%的选票才能当选` : 
                        getVoteRuleText(vote)
                      }}
                    </text>
                  </view>
                  <view class="vote-actions" v-if="!vote.hasVoted">
                    <button 
                      class="vote-btn approve-btn"
                      @click="voteOnProposal(vote.voteId, true)"
                    >
                      同意
                    </button>
                    <button 
                      class="vote-btn reject-btn"
                      @click="voteOnProposal(vote.voteId, false)"
                    >
                      反对
                    </button>
                  </view>
                  <view class="vote-status" v-else>
                    <text class="voted-status">您已投票: {{ vote.userVote ? '同意' : '反对' }}</text>
                    <button 
                      @click="withdrawVoteFromTask(vote.voteId)" 
                      class="withdraw-btn"
                      :disabled="withdrawLoading"
                      style="background: #ffc107; color: #333; padding: 6px 12px; border: none; border-radius: 4px; font-size: 12px; margin-top: 8px;"
                    >
                      {{ withdrawLoading ? '撤回中...' : '撤回投票' }}
                    </button>
                  </view>
                </view>
              </view>
            </view>

            <!-- 团队成员显示 -->
            <view v-if="teamInfo && teamInfo.members && teamInfo.members.length > 0" class="team-members-section">
              <text class="section-title">团队成员 ({{ teamInfo.members.length }})</text>
              <view class="members-list">
                <view 
                  v-for="member in teamInfo.members" 
                  :key="member.userId"
                  class="member-item"
                >
                  <image :src="getUserAvatar(member.userId)" class="member-avatar" @error="handleAvatarError" />
                  <view class="member-info">
                    <text class="member-name">{{ getUserNickname(member.userId) }}</text>
                    <text class="member-role">{{ (member.role === 1 || member.role === '1') ? '队长' : '队员' }}</text>
                    <text class="member-status" :class="'status-' + member.status">{{ member.statusText }}</text>
                  </view>
                  <view class="member-actions" v-if="!isTaskPublisher">
                    <!-- 队长可以发起踢人投票（仅任务进行中） -->
                    <button 
                      v-if="isTeamLeader && (member.role !== 1 && member.role !== '1') && taskData?.status === '2'"
                      class="vote-remove-btn"
                      @click="initiateRemoveMemberVote(member.userId)"
                    >
                      发起踢人投票
                    </button>
                    <!-- 队长可以转让队长（仅任务进行中） -->
                    <button 
                      v-if="isTeamLeader && (member.role !== 1 && member.role !== '1') && taskData?.status === '2'"
                      class="transfer-leader-btn"
                      @click="transferLeadership(member.userId)"
                    >
                      转让队长
                    </button>
                    <!-- 队员可以发起踢人投票（仅任务进行中） -->
                    <button 
                      v-if="!isTeamLeader && member.userId !== currentUserId && (member.role !== 1 && member.role !== '1') && taskData?.status === '2'"
                      class="vote-remove-btn"
                      @click="initiateRemoveMemberVote(member.userId)"
                    >
                      发起踢人投票
                    </button>
                    <!-- 队员可以发起弹劾队长投票（仅任务进行中） -->
                    <button 
                      v-if="!isTeamLeader && (member.role === 1 || member.role === '1') && taskData?.status === '2'"
                      class="impeach-leader-btn"
                      @click="initiateImpeachLeaderVote()"
                    >
                      弹劾队长
                    </button>
                    <!-- 队员可以申请退出团队 -->
                    <button 
                      v-if="!isTeamLeader && member.userId == currentUserId"
                      class="leave-team-btn"
                      @click="leaveTeam"
                    >
                      申请退出
                    </button>
                    
                    <!-- 调试信息 -->
                    <view style="font-size: 10px; color: red; padding: 8px; background: #fff3cd; border: 1px solid #ffc107; margin: 4px 0;">
                      <text style="font-weight: bold;">调试信息：</text><br/>
                      isTeamLeader: {{ isTeamLeader }}<br/>
                      taskStatus: {{ taskData?.status }}<br/>
                      member.role: {{ member.role }}<br/>
                      member.role原始值: {{ JSON.stringify(member.role) }}<br/>
                      member.userId: {{ member.userId }}<br/>
                      currentUserId: {{ currentUserId }}<br/>
                      isTaskPublisher: {{ isTaskPublisher }}<br/>
                      <view style="margin-top: 4px; font-weight: bold;">
                        条件检查结果：<br/>
                        踢人条件: {{ isTeamLeader && (member.role !== 1 && member.role !== '1') && taskData?.status === '2' }}<br/>
                        转让队长条件: {{ isTeamLeader && (member.role !== 1 && member.role !== '1') && taskData?.status === '2' }}<br/>
                        弹劾队长条件: {{ !isTeamLeader && (member.role === 1 || member.role === '1') && taskData?.status === '2' }}<br/>
                        退出条件: {{ !isTeamLeader && member.userId == currentUserId }}<br/>
                        详细检查: <br/>
                        - isTeamLeader值: {{ isTeamLeader }}<br/>
                        - member.role !== 1: {{ member.role !== 1 }}<br/>
                        - member.role !== '1': {{ member.role !== '1' }}<br/>
                        - taskData?.status === '2': {{ taskData?.status === '2' }}<br/>
                        - member.role === 1: {{ member.role === 1 }}<br/>
                        - member.role === '1': {{ member.role === '1' }}<br/>
                      </view>
                    </view>
                  </view>
                </view>
              </view>
            </view>
            
            <!-- 队长解散团队按钮（仅在组队阶段和任务完成后可解散） -->
            <view v-if="isTeamLeader && teamInfo && teamInfo.members && teamInfo.members.length > 0 && 
                       (taskData?.status === '1' || taskData?.status === '3')" class="dissolve-team-section">
              <button 
                class="dissolve-team-btn"
                @click="dissolveTeam"
              >
                解散团队
              </button>
            </view>
            
            <!-- 待处理邀请显示 -->
            <view v-if="teamInfo && teamInfo.pendingInvitations && teamInfo.pendingInvitations.length > 0" class="pending-invitations-section">
              <text class="section-title">待处理邀请 ({{ teamInfo.pendingInvitations.length }})</text>
              <view class="invitations-list">
                <view 
                  v-for="invitation in teamInfo.pendingInvitations" 
                  :key="invitation.userId"
                  class="invitation-item"
                >
                  <image :src="getUserAvatar(invitation.userId)" class="invitation-avatar" @error="handleAvatarError" />
                  <view class="invitation-info">
                    <text class="invitation-name">{{ getUserNickname(invitation.userId) }}</text>
                    <text class="invitation-time">{{ formatTime(invitation.sendTime) }}</text>
                  </view>
                </view>
              </view>
            </view>
            
            <!-- 团队名称输入（仅在没有团队信息时显示） -->
            <view v-if="!teamInfo" class="form-group">
              <text class="form-label">团队名称</text>
              <input 
                v-model="teamName" 
                class="form-input" 
                placeholder="请输入团队名称"
                maxlength="20"
              />
            </view>
            
            <!-- 好友选择（仅队长可见） -->
            <view v-if="isTeamLeader" class="form-group">
              <text class="form-label">邀请成员</text>
              <text class="form-hint">可以邀请好友或搜索其他用户加入团队</text>
              
              
              <view class="friend-search-section">
                <!-- 搜索框 -->
                <view class="search-input-group">
                  <input 
                    v-model="searchKeyword" 
                    class="search-input" 
                    :placeholder="teamInfo && teamInfo.status === 2 ? '团队已解散，无法邀请成员' : '输入好友昵称或UID搜索'"
                    :disabled="teamInfo && teamInfo.status === 2"
                    @input="searchFriends"
                  />
                  <button 
                    class="search-btn" 
                    :disabled="teamInfo && teamInfo.status === 2"
                    @click="searchFriends"
                  >
                    搜索
                  </button>
                </view>
                
                <!-- 解散状态提示 -->
                <view v-if="teamInfo && teamInfo.status === 2" class="dissolved-hint">
                  <text>团队已解散，无法邀请新成员。请先重新创建团队。</text>
                </view>
                
                <!-- 搜索结果 -->
                <view v-if="searchLoading" class="search-loading">搜索中...</view>
                <view v-else-if="searchError" class="search-error">{{ searchError }}</view>
                <view v-else-if="searchResults.length === 0 && searchKeyword" class="search-empty">
                  没有找到相关好友
                </view>
                <view v-else-if="searchResults.length > 0" class="search-results">
                  <view 
                    v-for="friend in searchResults" 
                    :key="friend.friendId || friend.uid || friend.id"
                    class="search-result-item"
                    :class="{ 
                      'is-friend': friend.friendStatus === 'accepted',
                      'not-friend': friend.friendStatus !== 'accepted'
                    }"
                  >
                    <image :src="getAvatarUrl(friend.avatarUrl || friend.friendAvatarUrl)" class="search-friend-avatar" @error="handleAvatarError" />
                    <view class="search-friend-info">
                      <view class="friend-name-row">
                        <text class="search-friend-name">{{ friend.friendNickname || friend.nickname || '未知用户' }}</text>
                        <view class="friend-status-badge" :class="friend.friendStatus">
                          <text v-if="friend.friendStatus === 'accepted'" class="status-text">好友</text>
                          <text v-else-if="friend.friendStatus === 'pending'" class="status-text">待确认</text>
                          <text v-else class="status-text">非好友</text>
                        </view>
                      </view>
                      <text class="search-friend-uid">UID: {{ friend.friendId || friend.uid || friend.id }}</text>
                    </view>
                    <view class="search-result-actions">
                      <button 
                        v-if="!isUserInvited(friend.friendId || friend.uid || friend.id)"
                        class="invite-btn"
                        @click="inviteSingleUser(friend.friendId || friend.uid || friend.id)"
                      >
                        邀请
                      </button>
                      <view v-else class="invited-status">
                        <text class="invited-text">已邀请</text>
                      </view>
                    </view>
                  </view>
                </view>
                <view v-else class="search-placeholder">
                  请输入好友昵称或UID开始搜索
                </view>
              </view>
            </view>
          </view>
          
          <!-- 申请按钮 -->
          <view class="application-buttons">
            <!-- 单人挑战申请按钮已移除：所有挑战现在都通过团队实现 -->
            
            <!-- 申请挑战按钮 -->
            <button 
              v-if="teamRole === 'leader'"
              @click="handleTeamApplication" 
              class="challenge-btn team-apply-btn"
              :disabled="!challengeContent.trim()"
            >
              <text>申请挑战</text>
            </button>
            
            <!-- 队员提示 -->
            <view v-if="teamRole === 'member'" class="member-notice">
              <text class="notice-text">您选择了队员角色</text>
              <text class="notice-hint">请等待队长邀请您加入团队，或联系队长创建团队</text>
              <button class="contact-leader-btn" @click="showContactLeaderModal">
                联系队长
              </button>
            </view>
          </view>
        </view>
      </view>
      <!-- 取消申请弹窗 -->
      <view v-if="showCancelRequestModal" class="modal-overlay" @click.self="closeCancelRequestModal">
        <view class="modal-content" @click.stop>
          <view class="modal-header">
            <text class="modal-title">申请取消任务</text>
            <button class="modal-close" @click="closeCancelRequestModal"><text>×</text></button>
          </view>
          <view class="modal-body">
            <view class="form-group">
              <text>取消原因：</text>
              <textarea 
                v-model="cancelReason" 
                :maxlength="200"
                :show-confirm-bar="false"
                :cursor-spacing="20"
                placeholder="请说明取消任务的原因..."
                class="cancel-reason-textarea"
              ></textarea>
              <view class="character-counter">
                <text>{{ formatCharacterCount(cancelReason.length) }}/200</text>
              </view>
            </view>
          </view>
          <view class="modal-footer">
            <button class="modal-cancel-btn" @click="closeCancelRequestModal">
              <text>取消</text>
            </button>
            <button class="modal-confirm-btn" @click="submitCancelRequest" :disabled="!cancelReason.trim()">
              <text>提交申请</text>
            </button>
          </view>
        </view>
      </view>
      
      <!-- 任务修改弹窗 -->
      <view v-if="showEditTaskModal" class="modal-overlay" @click.self="closeEditTaskModal">
        <view class="modal-content edit-task-modal" @click.stop>
          <view class="modal-header">
            <text class="modal-title">修改任务信息</text>
            <button class="modal-close" @click="closeEditTaskModal"><text>×</text></button>
          </view>
          <view class="modal-body">
            <!-- 修改次数提示 -->
            <view class="edit-count-info">
              <text class="edit-count-text">修改次数：{{ taskEditInfo?.editCount || 0 }}/3</text>
              <text class="remaining-edits">剩余修改次数：{{ taskEditInfo?.remainingEdits || 3 }}</text>
            </view>
            
            <view class="form-group">
              <text>任务标题：</text>
              <input 
                v-model="editTaskForm.title" 
                :maxlength="100"
                placeholder="请输入任务标题"
                class="edit-input"
              />
            </view>
            
            <view class="form-group">
              <text>任务描述：</text>
              <textarea 
                v-model="editTaskForm.description" 
                :maxlength="1000"
                :show-confirm-bar="false"
                :cursor-spacing="20"
                placeholder="请输入任务描述"
                class="edit-textarea"
              ></textarea>
              <view class="character-counter">
                <text>{{ editTaskForm.description.length }}/1000</text>
              </view>
            </view>
            
            <view class="form-group">
              <text>任务地址：</text>
              <input 
                v-model="editTaskForm.address" 
                :maxlength="200"
                placeholder="请输入任务地址"
                class="edit-input"
              />
            </view>
            
            <view class="form-group">
              <text>悬赏金额：</text>
              <input 
                v-model="editTaskForm.reward" 
                type="number"
                placeholder="请输入悬赏金额"
                class="edit-input"
              />
            </view>
          </view>
          <view class="modal-footer">
            <button class="modal-cancel-btn" @click="closeEditTaskModal">
              <text>取消</text>
            </button>
            <button class="modal-confirm-btn" @click="submitEditTask" :disabled="!canSubmitEdit">
              <text>保存修改</text>
            </button>
          </view>
        </view>
      </view>

      <view id="apply-complete-anchor"></view>
      
      <!-- 申请完成详情显示（发布者查看对方提交的申请） -->
      <view v-if="isPublisherAndInProgress && showCompletePreview" class="apply-complete-preview-section">
        <text class="apply-complete-title">申请完成详情</text>
        <view class="form-group">
          <text>完成证明：</text>
          <view class="complete-proof-container">
            <view class="preview-proof">{{ completePreview?.proof || '—' }}</view>
          </view>
        </view>
        <view class="form-group">
          <text>铭牌分配：</text>
          <view v-if="completePreview?.badges && completePreview.badges.length">
            <view v-for="b in completePreview.badges" :key="b.badgeId" class="badge-form">
              <view>
                <text>{{ getBadgeNameByAssociation(b.association || b.assoc) || '徽章' }} Lv{{ formatNumber(b.level || 0) }}</text>
              </view>
              <view v-for="(c, idx) in b.contributors" :key="idx" class="contributor-form">
                <text>贡献者</text>
                <view class="contributor-selector">
                  <image 
                    :src="getSafeUserAvatar(c.uid)" 
                    class="contributor-avatar-small" 
                    mode="aspectFill"
                    @error="handleAvatarError"
                  />
                  <text class="contributor-name">{{ getUserName(c.uid) }}</text>
                </view>
                <text>角色</text>
                <view class="preview-field">{{ c.role || '—' }}</view>
                <text>贡献比例(%)</text>
                <view class="preview-field">{{ formatPercentage(c.percentage) }}%</view>
              </view>
            </view>
          </view>
          <text v-else>暂无数据</text>
        </view>
      </view>
      
      <view v-if="showApplyCompleteBtn" class="apply-complete-section">
        <text class="apply-complete-title">申请完成任务</text>
        <view class="form-group">
          <text>完成证明：</text>
          <view class="complete-proof-container">
            <textarea 
              v-model="completeProof" 
              :maxlength="500"
              :show-confirm-bar="false"
              :cursor-spacing="20"
              placeholder="请填写完成证明"
              class="complete-proof-textarea"
            ></textarea>
            <view class="character-counter">
              <text>{{ formatCharacterCount(completeProof.length) }}/500</text>
            </view>
          </view>
        </view>
        <view class="form-group" v-if="canShowBadgeAllocation">
          <text>铭牌分配：</text>
          <view v-for="badge in taskData?.badges" :key="badge.id" class="badge-form">
            <view>
              <text>{{ getBadgeNameByAssociation(badge.association) }} Lv{{ formatNumber(badge.level) }}</text>
            </view>
            <view v-for="(contributor, index) in badgeContributors[badge.id]" :key="index" class="contributor-form">
              <text>分配给队员</text>
              <view class="contributor-selector">
                <TeamMemberSelector
                  v-if="!(index === 0 && contributor.uid === currentUserId)"
                  :currentUserId="currentUserId"
                  :disabled="!canEditBadgeAllocation"
                  :teamMembers="getTeamMembersForBadge()"
                  @select="(member) => selectContributor(badge.id, index, member)"
                  @clear="() => clearContributor(badge.id, index)"
                />
                <view v-else class="current-user-display">
                  <text>当前用户 ({{ currentUserId }})</text>
                </view>
              </view>
              <text>角色</text>
              <input 
                type="text" 
                v-model="contributor.role" 
                :disabled="!canEditBadgeAllocation"
                placeholder="可选，如：开发者/设计师"
              />
              <text>贡献比例(%)</text>
              <input 
                type="number" 
                v-model.number="contributor.percentage" 
                :disabled="!canEditBadgeAllocation"
                min="1" 
                max="100" 
                @input="debouncedValidateTotalPercentage(badge.id)"
              />
              <button 
                v-if="!(index === 0 && contributor.uid === currentUserId) && canEditBadgeAllocation" 
                @click="removeContributor(badge.id, index)" 
                class="remove-btn"
              >
                <text>删除</text>
              </button>
            </view>
            <view class="percentage-total">
              <text>总百分比: {{ formatPercentage(calculateTotalPercentage(badge.id)) }}% </text>
              <text v-if="calculateTotalPercentage(badge.id) !== 100" class="error-text">(必须等于100%)</text>
            </view>
            <button v-if="canEditBadgeAllocation" @click="addContributor(badge.id)" class="add-btn"><text>添加贡献者</text></button>
          </view>
        </view>
        <button 
          v-if="!hasAppliedCompletion"
          @click="applyCompleteTask" 
          class="apply-complete-btn"
          :disabled="!canSubmitComplete"
        ><text>申请完成任务</text></button>
        <view v-else class="applied-actions">
          <button class="apply-complete-btn" disabled><text>已申请完成</text></button>
          <button class="cancel-apply-btn" @click="cancelCompletionByTask"><text>撤回完成申请</text></button>
        </view>
      </view>
      
      <!-- 申请完成处理按钮（页面底部） -->
      <view v-if="isPublisherAndInProgress && showCompletePreview" class="completion-actions-bottom">
        <button class="reject-completion-btn" @click="handleRejectCompletion">
          <text>驳回申请</text>
        </button>
        <button class="approve-completion-btn" @click="handleApproveCompletion">
          <text>同意申请</text>
        </button>
    </view>
      
    </view>
    
    <!-- 组队邀请模态框 -->
    <TeamInvitationModal 
      :show="showTeamInvitationModal"
      :taskId="taskData?.taskId"
      :teamInfo="teamInfo"
      @close="closeTeamInvitationModal"
      @confirm="handleTeamInvitationConfirm"
      @updateTeamName="handleUpdateTeamName"
    />
  </scroll-view>
</template>

<script>
import { NETWORK_CONFIG } from '@/config/network.js'
import { getBadgeNameByAssociation } from "@/utils/skillUtils";
import { ref, computed, watch, reactive } from "vue";
import { onLoad, onShow, onHide, onUnload } from '@dcloudio/uni-app';
import { useUserStore } from '@/store/user'
import { getAvatarUrl } from '@/utils/imageUtils.js'
import FriendSelector from '@/components/FriendSelector.vue'
import TeamInvitationModal from '@/components/TeamInvitationModal.vue'
import TeamMemberSelector from '@/components/TeamMemberSelector.vue'
import { getAvatarDisplayUrl } from '@/utils/imageUtils.js'

export default {
  name: "TaskDetail",
  components: {
    FriendSelector,
    TeamInvitationModal,
    TeamMemberSelector
  },
  setup() {
    let map3D = null;
    let marker3D = null;
    const task = ref(null);
    const loading = ref(true);
    const error = ref(null);
    let taskId = null;
    const refreshing = ref(false);
    const scrollIntoView = ref('');
    
    // 任务修改相关状态
    const showEditTaskModal = ref(false);
    const editTaskForm = reactive({
      title: '',
      description: '',
      address: '',
      reward: null
    });
    const taskEditInfo = reactive({
      editCount: 0,
      remainingEdits: 3
    });
    const mapMarkers = computed(() => {
      if (!task.value || !task.value.longitude || !task.value.latitude) {
        return [{
          id: 1,
          longitude: 116.397128,
          latitude: 39.916527,
          title: '默认位置',
          width: 30,
          height: 30
        }];
      }
      return [{
        id: 1,
        longitude: parseFloat(task.value.longitude),
        latitude: parseFloat(task.value.latitude),
        title: task.value.title || '任务位置',
        width: 30,
        height: 30
      }];
    });


    const applyForTask = async () => {
      if (!challengeContent.value.trim()) {
        uni.showToast({ title: "请输入申请理由！", icon: 'none' });
        return;
      }
      uni.showLoading({ title: '提交申请中...' });
      try {
        const token = uni.getStorageSync("accessToken");
        if (!token) {
          uni.showToast({ title: "请先登录", icon: 'none' });
          return;
        }
        
        // 构建请求数据，放在 request body 中
        const requestData = {
          taskId: task.value.taskId,
          content: challengeContent.value.trim()
        };
        
        // 如果是团队申请，添加teamId
        if (teamInfo.value && teamInfo.value.teamId) {
          requestData.teamId = teamInfo.value.teamId;
        }
        
        const response = await uni.request({
          url: `${NETWORK_CONFIG.API_BASE_URL}/task/apply`,
          method: 'POST',
          data: requestData,
          header: {
            'Content-Type': 'application/json',
            'Access-Token': `Bearer ${token}`,
          },
        });
        if (response.statusCode === 200) {
          uni.hideLoading();
          uni.showToast({ title: response.data.message || "申请成功！", icon: 'success' });
          // 申请成功后刷新页面
          await fetchTaskDetail(task.value.taskId);
          await checkUserApplied(); // 重新检查用户申请状态
        } else {
          throw new Error(response.data?.message || `申请失败，状态码: ${response.statusCode}`);
        }
      } catch (err) {
        uni.hideLoading();
        uni.showToast({ title: err.message || "申请失败，请稍后重试！", icon: 'none', duration: 3000 });
      }
    };
    const getStatusText = (status) => {
      switch (status) {
        case "0": return "审核中";
        case "1": return "未完成";
        case "2": return "进行中";
        case "3": return "已完成";
        default: return "未知状态";
      }
    };
    const addContributor = (badgeId) => {
      if (!badgeContributors[badgeId]) badgeContributors[badgeId] = [];
      badgeContributors[badgeId].push({ uid: '', role: '', percentage: 0 });
      redistributePercentage(badgeId);
    };
    const removeContributor = (badgeId, index) => {
      badgeContributors[badgeId].splice(index, 1);
      redistributePercentage(badgeId);
    };
    const selectContributor = (badgeId, index, member) => {
      if (badgeContributors[badgeId] && badgeContributors[badgeId][index]) {
        badgeContributors[badgeId][index].uid = member.userId;
        badgeContributors[badgeId][index].nickname = member.nickname;
      }
    };
    const clearContributor = (badgeId, index) => {
      if (badgeContributors[badgeId] && badgeContributors[badgeId][index]) {
        badgeContributors[badgeId][index].uid = '';
        badgeContributors[badgeId][index].nickname = '';
      }
    };
    
    // 获取团队成员数据，转换为TeamMemberSelector需要的格式
    const getTeamMembersForBadge = () => {
      if (!teamInfo.value || !teamInfo.value.members) {
        return [];
      }
      
      return teamInfo.value.members.map(member => ({
        userId: member.userId,
        nickname: getUserNickname(member.userId),
        avatarUrl: getUserAvatar(member.userId),
        role: member.role
      }));
    };
    const calculateTotalPercentage = (badgeId) => {
      if (!badgeContributors[badgeId]) return 0;
      return badgeContributors[badgeId].reduce((sum, contributor) => sum + (contributor.percentage || 0), 0);
    };
    const validateTotalPercentage = (badgeId) => {
      const total = calculateTotalPercentage(badgeId);
    };
    const redistributePercentage = (badgeId) => {
      const contributors = badgeContributors[badgeId];
      if (!contributors || contributors.length === 0) return;
      if (contributors.length === 1) {
        contributors[0].percentage = 100;
        return;
      }
      const equalShare = Math.floor(100 / contributors.length);
      const remainder = 100 - (equalShare * contributors.length);
      contributors.forEach((contributor, index) => {
        contributor.percentage = equalShare + (index === 0 ? remainder : 0);
      });
    };
    const defaultAvatar = "https://example.com/default-avatar.jpg";
    const userStore = useUserStore();
    const challengeContent = ref("");
    const completeProof = ref('');
    const showCompletePreview = ref(false);
    const previewLoading = ref(false);
    const previewError = ref('');
    const completePreview = ref(null);
    
    
    // 任务取消相关状态
    const showCancelRequestModal = ref(false);
    const cancelReason = ref('');
    const taskStatus = ref(null);
    const badgeContributions = reactive({});
    const badgeContributors = reactive({});
    const initializeBadgeContributors = () => {
      if (taskData.value && Array.isArray(taskData.value.badges)) {
        // 获取团队成员列表（优先使用 teamInfo，如果没有则尝试从任务数据获取）
        const teamMembers = teamInfo.value?.members || [];
        
        console.log('初始化铭牌分配，团队成员数:', teamMembers.length, '铭牌数:', taskData.value.badges.length);
        
        taskData.value.badges.forEach(badge => {
          if (teamMembers.length > 0) {
            // 如果是团队任务，为所有成员均分铭牌
            const memberCount = teamMembers.length;
            // 计算每人应得比例（向下取整），余数分配给第一个成员
            const equalShare = Math.floor(100 / memberCount);
            const remainder = 100 - (equalShare * memberCount);
            
            badgeContributors[badge.id] = teamMembers.map((member, index) => {
              // 确保每人至少1%
              const percentage = index === 0 ? equalShare + remainder : equalShare;
              return {
                uid: String(member.userId),
                nickname: getUserNickname(member.userId),
                role: member.role === 1 || member.role === '1' ? '队长' : '队员',
                percentage: Math.max(1, percentage) // 确保至少1%
              };
            });
            
            console.log(`铭牌 ${badge.id} 分配完成，成员数: ${memberCount}，每人分配:`, badgeContributors[badge.id]);
          } else {
            // 如果不是团队任务（单人），默认分配给当前用户
            badgeContributors[badge.id] = [{
              uid: String(currentUserId.value),
              role: '主要贡献者',
              percentage: 100
            }];
            console.log(`铭牌 ${badge.id} 分配给单人:`, currentUserId.value);
          }
        });
      }
    };
    // 监听任务数据变化，初始化铭牌分配
    watch(() => taskData.value, (newTaskData) => {
      if (newTaskData && Array.isArray(newTaskData.badges)) {
        newTaskData.badges.forEach(badge => { badgeContributions[badge.id] = 100; });
        // 延迟初始化，确保 teamInfo 已加载
        setTimeout(() => {
          initializeBadgeContributors();
        }, 100);
      }
    }, { immediate: true });
    
    // 监听团队信息变化，重新初始化铭牌分配
    watch(() => teamInfo.value?.members, (newMembers) => {
      if (newMembers && newMembers.length > 0 && taskData.value && Array.isArray(taskData.value.badges)) {
        console.log('团队信息变化，重新初始化铭牌分配，成员数:', newMembers.length);
        initializeBadgeContributors();
      }
    }, { deep: true });
    const showApplyCompleteBtn = computed(() => {
      if (!taskData.value || !currentUserId.value) {
        console.log('showApplyCompleteBtn: 缺少必要数据', { 
          hasTaskData: !!taskData.value, 
          hasCurrentUserId: !!currentUserId.value 
        });
        return false;
      }
      const challengerId = taskData.value.challengerId;
      const teamId = taskData.value.teamId;
      const status = taskData.value.status;
      const publisherId = taskData.value.publisherId;
      
      // 发布者不应该看到申请完成按钮
      const isPublisher = String(publisherId) === String(currentUserId.value);
      if (isPublisher) {
        console.log('showApplyCompleteBtn: 发布者不应该看到申请完成按钮');
        return false;
      }
      
      // 现在所有任务都是团队任务，检查用户是否是团队成员
      const isChallenger = teamInfo.value && teamInfo.value.members && 
        teamInfo.value.members.some(member => String(member.userId) === String(currentUserId.value));
      
      const result = isChallenger && String(status) === '2';
      console.log('showApplyCompleteBtn 计算结果:', {
        challengerId,
        teamId,
        currentUserId: currentUserId.value,
        status,
        isTeamTask: isTeamTask(),
        isChallenger,
        isPublisher,
        statusMatch: String(status) === '2',
        result
      });
      return result;
    });
    const isPublisherAndInProgress = computed(() => {
      if (!taskData.value || !currentUserId.value) return false;
      return String(taskData.value.publisherId) === String(currentUserId.value) && String(taskData.value.status) === '2';
    });

    // 任务操作相关计算属性
    const showTaskActions = computed(() => {
      if (!taskData.value || !currentUserId.value) return false;
      const status = taskData.value.status;
      const publisherId = taskData.value.publisherId;
      const challengerId = taskData.value.challengerId;
      const teamId = taskData.value.teamId;
      const isPublisher = String(publisherId) === String(currentUserId.value);
      
      // 现在所有任务都是团队任务，检查用户是否是团队成员
      const isChallenger = teamInfo.value && teamInfo.value.members && 
        teamInfo.value.members.some(member => String(member.userId) === String(currentUserId.value));
      
      console.log('showTaskActions 调试信息:', {
        isPublisher,
        isChallenger,
        hasUserApplied: hasUserApplied.value,
        status: taskData.value?.status,
        publisherId: taskData.value?.publisherId,
        teamId: taskData.value?.teamId,
        currentUserId: currentUserId.value,
        result: isPublisher || isChallenger || hasUserApplied.value
      });
      
      // 发布者、挑战者或申请者都可以看到操作按钮
      return isPublisher || isChallenger || hasUserApplied.value;
    });

    const canCancelApply = computed(() => {
      if (!taskData.value || !currentUserId.value) return false;
      const status = taskData.value.status;
      const challengerId = taskData.value.challengerId;
      const teamId = taskData.value.teamId;
      
      // 现在所有任务都是团队任务，检查用户是否是团队成员
      const isChallenger = teamInfo.value && teamInfo.value.members && 
        teamInfo.value.members.some(member => String(member.userId) === String(currentUserId.value));
      
      console.log('canCancelApply 调试信息:', {
        status,
        teamId,
        isChallenger,
        hasUserApplied: hasUserApplied.value,
        currentUserId: currentUserId.value,
        result: (isChallenger && String(status) === '1') || (String(status) === '1' && hasUserApplied.value)
      });
      
      // 只有申请者可以撤回申请，且任务状态为1（可申请状态）
      // 或者当前用户申请了任务但teamId还未设置（通过消息记录判断）
      return (isChallenger && String(status) === '1') || 
             (String(status) === '1' && hasUserApplied.value);
    });

    const canRequestCancel = computed(() => {
      if (!taskData.value || !currentUserId.value) return false;
      const status = taskData.value.status;
      const publisherId = taskData.value.publisherId;
      const challengerId = taskData.value.challengerId;
      const teamId = taskData.value.teamId;
      const isPublisher = String(publisherId) === String(currentUserId.value);
      
      // 现在所有任务都是团队任务，检查用户是否是团队成员
      const isChallenger = teamInfo.value && teamInfo.value.members && 
        teamInfo.value.members.some(member => String(member.userId) === String(currentUserId.value));
      
      // 只有任务相关方可以申请取消，且任务状态为2（进行中）
      return (isPublisher || isChallenger) && String(status) === '2';
    });

    const canDeleteTask = computed(() => {
      if (!taskData.value || !currentUserId.value) return false;
      const status = taskData.value.status;
      const publisherId = taskData.value.publisherId;
      const isPublisher = String(publisherId) === String(currentUserId.value);
      
      // 只有发布者可以删除任务，且任务状态为0或1
      return isPublisher && (String(status) === '0' || String(status) === '1');
    });

    const canEditTask = computed(() => {
      if (!taskData.value || !currentUserId.value) return false;
      const status = taskData.value.status;
      const publisherId = taskData.value.publisherId;
      const isPublisher = String(publisherId) === String(currentUserId.value);
      
      // 只有发布者可以修改任务，且任务状态为1或2，修改次数未达上限
      return isPublisher && (String(status) === '1' || String(status) === '2') && 
             (taskEditInfo.value?.editCount || 0) < 3;
    });

    // 检查是否有待处理的消息
    const hasPendingMessages = ref(false);
    const pendingMessageTypes = ref([]);
    const hasAppliedCompletion = ref(false);
    
    // 检查用户是否申请了该任务
    const hasUserApplied = ref(false);
    
    // 组队相关状态
    const showTeamInvitationModal = ref(false);
    const teamInfo = ref(null);
    const teamMembers = ref([]);
    const teamStatus = ref(null); // 0-组建中, 1-已组建, 2-已解散
    
    // 新的组队模式状态
    const teamMode = ref(false); // 是否启用组队模式
    const teamName = ref(''); // 团队名称
    const editingTeamName = ref(''); // 编辑中的团队名称
    const userInfoCache = ref({}); // 用户信息缓存
    
    // 挑战类型选择状态（所有挑战现在都通过团队实现）
    const challengeType = ref('team'); // 现在只支持'team'，单人挑战通过创建一个只有一个人的团队来实现
    const teamRole = ref('leader'); // 'leader' | 'member'
    
    // 搜索相关状态
    const searchKeyword = ref('');
    const searchResults = ref([]);
    const searchLoading = ref(false);
    const searchError = ref(null);
    const invitedUsers = ref(new Set()); // 已邀请的用户
    const isTeamLeader = ref(false); // 是否是队长
    
    // 投票相关状态
    const activeTeamVotes = ref([]); // 进行中的投票
    const voteHistory = ref([]); // 投票记录（历史）
    const voteLoading = ref(false); // 投票提交中
    const withdrawLoading = ref(false); // 撤回投票中
    const selectedCandidateId = ref(null); // 选中的候选人ID（选举投票用）

    // 解析JWT token的工具函数（兼容微信小程序）
    const parseJwtToken = (token) => {
      try {
        const tokenParts = token.split('.');
        if (tokenParts.length !== 3) {
          throw new Error('Invalid token format');
        }
        
        const payloadBase64 = tokenParts[1];
        // 添加填充字符以确保 base64 长度正确
        const paddedBase64 = payloadBase64 + '='.repeat((4 - payloadBase64.length % 4) % 4);
        
        // 在微信小程序环境中使用 uni.base64ToArrayBuffer
        const arrayBuffer = uni.base64ToArrayBuffer(paddedBase64);
        const payloadString = String.fromCharCode.apply(null, new Uint8Array(arrayBuffer));
        return JSON.parse(payloadString);
      } catch (error) {
        console.error('解析JWT token失败:', error);
        return null;
      }
    };

    // 跳转到修改任务页面
    const goToEditTask = () => {
      uni.navigateTo({
        url: `/pages/task/publish/index?taskId=${taskId}&mode=edit`
      });
    };

    // 任务修改相关方法
    const openEditTaskModal = async () => {
      try {
        // 获取任务修改信息
        const token = uni.getStorageSync('accessToken');
        const response = await uni.request({
          url: `${NETWORK_CONFIG.API_BASE_URL}/task/edit-info?taskId=${taskId}`,
          method: 'GET',
          header: { 'Access-Token': `Bearer ${token}` }
        });
        
        if (response.data && response.data.success) {
          taskEditInfo.value.editCount = response.data.editCount || 0;
          taskEditInfo.value.remainingEdits = response.data.remainingEdits || 3;
        }
        
        // 填充表单数据
        editTaskForm.title = taskData.value.title || '';
        editTaskForm.description = taskData.value.description || '';
        editTaskForm.address = taskData.value.address || '';
        editTaskForm.reward = taskData.value.reward || 0;
        
        showEditTaskModal.value = true;
      } catch (error) {
        console.error('获取任务修改信息失败:', error);
        uni.showToast({ title: '获取修改信息失败', icon: 'none' });
      }
    };
    
    const closeEditTaskModal = () => {
      showEditTaskModal.value = false;
      // 重置表单
      editTaskForm.title = '';
      editTaskForm.description = '';
      editTaskForm.address = '';
      editTaskForm.reward = null;
    };
    
    const submitEditTask = async () => {
      try {
        const token = uni.getStorageSync('accessToken');
        const response = await uni.request({
          url: `${NETWORK_CONFIG.API_BASE_URL}/task/request-update`,
          method: 'POST',
          data: {
            taskId: taskId,
            title: editTaskForm.title,
            description: editTaskForm.description,
            address: editTaskForm.address,
            reward: editTaskForm.reward
          },
          header: { 'Access-Token': `Bearer ${token}` }
        });
        
        if (response.data && response.data.success) {
          uni.showToast({ title: '修改申请已提交，等待队长同意', icon: 'success' });
          closeEditTaskModal();
          // 重新加载任务数据
          await fetchTaskDetail(taskId);
        } else {
          uni.showToast({ title: response.data?.message || '提交失败', icon: 'none' });
        }
      } catch (error) {
        console.error('提交任务修改失败:', error);
        uni.showToast({ title: '提交失败，请重试', icon: 'none' });
      }
    };
    
    const canSubmitEdit = computed(() => {
      return editTaskForm.title.trim() && 
             editTaskForm.description.trim() && 
             editTaskForm.address.trim() && 
             editTaskForm.reward > 0 &&
             (taskEditInfo.value?.editCount || 0) < 3;
    });
    
    // 获取任务类型文本（现在所有任务都是团队任务）
    const getTaskTypeText = () => {
      return '团队任务';
    };
    
    // 判断是否为团队任务（现在所有任务都是团队任务，只要存在teamId就认为是团队任务）
    const isTeamTask = () => {
      if (!taskData.value) return false;
      // 只要有teamId就认为是团队任务
      return !!(taskData.value.teamId || (teamInfo.value && teamInfo.value.members && teamInfo.value.members.length > 0));
    };
    

    // 获取用户消息状态
    const checkPendingMessages = async () => {
      try {
        const token = uni.getStorageSync('accessToken');
        if (!token) return;
        
        const taskIdVal = taskData.value?.taskId || task.value?.taskId;
        if (!taskIdVal) return;
        
        const response = await uni.request({
          url: `${NETWORK_CONFIG.API_BASE_URL}/message/pending?taskId=${taskIdVal}`,
          method: 'GET',
          header: { 'Access-Token': `Bearer ${token}` },
          timeout: 8000
        });
        
        if (response.statusCode === 200 && response.data) {
          hasPendingMessages.value = response.data.hasPending;
          pendingMessageTypes.value = response.data.messageTypes || [];
          // 注意：pendingMessageTypes 是别人发给我的待处理消息，不用于判断我是否已申请完成
          // hasAppliedCompletion 应该通过专门的 check-completion-apply 接口来设置
        }
      } catch (e) {
        console.log('检查待处理消息失败:', e);
      }
    };

    // 检查用户是否申请了该任务
    const checkUserApplied = async () => {
      try {
        const token = uni.getStorageSync('accessToken');
        if (!token) return;
        
        const taskIdVal = taskData.value?.taskId || task.value?.taskId;
        if (!taskIdVal) return;
        
        const response = await uni.request({
          url: `${NETWORK_CONFIG.API_BASE_URL}/message/check-apply?taskId=${taskIdVal}`,
          method: 'GET',
          header: { 'Access-Token': `Bearer ${token}` },
          timeout: 8000
        });
        
        if (response.statusCode === 200 && response.data) {
          hasUserApplied.value = response.data.hasApplied || false;
          console.log('检查用户申请状态结果:', {
            taskId: taskIdVal,
            hasApplied: hasUserApplied.value,
            response: response.data
          });
          
          // 强制触发响应式更新
          console.log('hasUserApplied 更新后:', hasUserApplied.value);
          
          // 强制触发计算属性重新计算
          setTimeout(() => {
            console.log('延迟检查 canCancelApply:', {
              hasUserApplied: hasUserApplied.value,
              status: taskData.value?.status,
              hasPendingMessages: hasPendingMessages.value,
              canCancelApply: canCancelApply.value,
              showTaskActions: showTaskActions.value
            });
          }, 100);
        }
        // 同时检查是否有未处理的完成申请，驱动"撤回完成申请"按钮显示
        try {
          const resp2 = await uni.request({
            url: `${NETWORK_CONFIG.API_BASE_URL}/message/check-completion-apply?taskId=${taskIdVal}`,
            method: 'GET',
            header: { 'Access-Token': `Bearer ${token}` },
            timeout: 8000
          });
          if (resp2.statusCode === 200 && resp2.data) {
            hasAppliedCompletion.value = !!resp2.data.hasApplied;
          }
        } catch (_) {}
      } catch (e) {
        console.log('检查用户申请状态失败:', e);
      }
    };
    const taskData = computed(() => {
      if (!task.value) return null;
      
      return {
        title: task.value.title || '',
        userName: task.value.publisherName || task.value.userName || '未知用户',
        orgName: task.value.orgName || '未知企业',
        publishTime: task.value.publishTime || '',
        deadline: task.value.deadline || '',
        description: task.value.description || '',
        reward: task.value.reward || 0,
        currentPaid: task.value.currentPaid || 0,
        status: task.value.status || '',
        challengerId: task.value.challengerId || null,
        teamId: task.value.teamId || null,
        publisherId: task.value.publisherId || null,
        userAvatar: getAvatarUrl(task.value.userAvatar),
        longitude: task.value.longitude || 116.397128,
        latitude: task.value.latitude || 39.916527,
        badges: task.value.badges || [],
        taskId: task.value.taskId || null
      };
    });
    const currentUserId = computed(() => userStore.profile?.uid || null);
    
    // 是否可以显示组队模式复选框
    const canShowTeamMode = computed(() => {
      // 如果任务状态为2（进行中），禁止创建团队，但允许查看团队信息
      if (taskData.value?.status === '2') {
        // 任务发布者可以查看团队信息
        const isPublisher = taskData.value?.publisherId && 
          String(taskData.value.publisherId) === String(currentUserId.value);
        return isPublisher;
      }
      // 现在所有任务都是团队任务，如果用户是团队成员但没有团队信息，不显示组队模式
      const isTeamMember = teamInfo.value && teamInfo.value.members && 
        teamInfo.value.members.some(member => String(member.userId) === String(currentUserId.value));
      if (isTeamMember && !teamInfo.value) {
        return false;
      }
      return true;
    });

    // 是否可以显示团队信息（包括任务发布者查看）
    const canShowTeamInfo = computed(() => {
      // 如果有团队信息，总是显示
      if (teamInfo.value) {
        return true;
      }
      // 任务发布者在任务进行中时也可以查看团队信息
      if (taskData.value?.status === '2') {
        const isPublisher = taskData.value?.publisherId && 
          String(taskData.value.publisherId) === String(currentUserId.value);
        return isPublisher;
      }
      return false;
    });

    // 是否是任务发布者
    const isTaskPublisher = computed(() => {
      return taskData.value?.publisherId && 
        String(taskData.value.publisherId) === String(currentUserId.value);
    });
    
    // 是否可以显示铭牌分配
    const canShowBadgeAllocation = computed(() => {
      if (!taskData.value || !currentUserId.value) return false;
      
      const status = taskData.value.status;
      const publisherId = taskData.value.publisherId;
      const challengerId = taskData.value.challengerId;
      const isPublisher = String(publisherId) === String(currentUserId.value);
      
      // 发布者可以看到铭牌分配，但不能修改
      if (isPublisher) {
        console.log('canShowBadgeAllocation: 发布者可以看到铭牌分配（只读）');
        return true;
      }
      
      // 如果任务状态为2（进行中），挑战者可以看到铭牌分配
      if (String(status) === '2') {
        // 现在所有任务都是团队任务，检查用户是否是团队成员
        const isTeamMember = teamInfo.value && teamInfo.value.members && 
          teamInfo.value.members.some(member => String(member.userId) === String(currentUserId.value));
        return isTeamMember;
      }
      
      // 其他状态下的逻辑：现在所有任务都是团队任务
      const isTeamMember = teamInfo.value && teamInfo.value.members && 
        teamInfo.value.members.some(member => String(member.userId) === String(currentUserId.value));
      if (isTeamMember && !teamInfo.value) {
        return false;
      }
      return true;
    });
    
    // 是否可以修改铭牌分配（只有队长可以修改）
    const canEditBadgeAllocation = computed(() => {
      if (!taskData.value || !currentUserId.value) return false;
      
      const publisherId = taskData.value.publisherId;
      const isPublisher = String(publisherId) === String(currentUserId.value);
      
      // 发布者不能修改铭牌分配
      if (isPublisher) {
        console.log('canEditBadgeAllocation: 发布者不能修改铭牌分配');
        return false;
      }
      
      // 现在所有任务都是团队任务，只有队长可以修改铭牌分配
      if (!teamInfo.value || !teamInfo.value.members) return false;
      
      // 检查用户是否是队长
      const isLeader = teamInfo.value.members.some(member => 
        String(member.userId) === String(currentUserId.value) && 
        (member.role === 1 || member.role === '1')
      );
      
      console.log('canEditBadgeAllocation: 团队任务，用户是否是队长:', isLeader);
      return isLeader;
    });
    
    const moveToTaskLocation = () => {
      if (!task.value || !task.value.longitude || !task.value.latitude) {
        uni.showToast({ title: '任务位置信息无效', icon: 'none' });
        return;
      }
      const mpLongitude = parseFloat(task.value.longitude);
      const mpLatitude = parseFloat(task.value.latitude);
      if (isNaN(mpLongitude) || isNaN(mpLatitude)) {
        uni.showToast({ title: '任务坐标无效', icon: 'none' });
        return;
      }
      // 关键代码：让地图回正
      const mapCtx = uni.createMapContext('map3D');
      mapCtx.moveToLocation({
        longitude: mpLongitude,
        latitude: mpLatitude
      });
    };
    const fetchTaskDetail = async (taskId) => {
      try {
        const networkType = await uni.getNetworkType();
        if (networkType.networkType === 'none') {
          throw new Error('网络连接不可用，请检查网络设置');
        }
        const response = await uni.request({
          url: `${NETWORK_CONFIG.API_BASE_URL}/task/detail`,
          method: 'GET',
          data: { taskId },
          timeout: 10000
        });
        if (response.statusCode === 200) {
          let data = response.data;
          // 后端可能返回字符串形式的JSON，做一次安全解析
          if (typeof data === 'string') {
            try { data = JSON.parse(data); } catch (_) {}
          }
          task.value = data;
          
          // 如果任务有挑战者且状态为进行中，加载团队信息
          if (data.challengerId && (data.status === 2 || data.status === '2')) {
            // 优先使用teamId，如果没有则使用challengerId
            const teamId = data.teamId || data.challengerId;
            await loadTeamInfo(teamId);
          }
          
          // 若详情内带有工作记录（TaskService.detail 已包含 workTimes），初始化它
          try {
            const rawWorkTimes = data?.workTimes;
            if (rawWorkTimes) {
              if (Array.isArray(rawWorkTimes)) {
                workTimes.value = rawWorkTimes;
              } else if (typeof rawWorkTimes === 'string') {
                const parsed = JSON.parse(rawWorkTimes);
                if (Array.isArray(parsed)) workTimes.value = parsed;
              }
            }
          } catch (_) {}
          console.log('任务详情加载成功:', {
            taskData: response.data,
            challengerId: response.data?.challengerId,
            status: response.data?.status,
            publisherId: response.data?.publisherId,
            publisherName: response.data?.publisherName,
            orgName: response.data?.orgName,
            userAvatar: response.data?.userAvatar
          });
        } else {
          throw new Error(`服务器响应错误: ${response.statusCode}`);
        }
      } catch (err) {
        error.value = `加载任务详情失败: ${err.message}`;
      } finally {
        loading.value = false;
      }
    };
    const onRefresh = async () => {
      if (!taskId) return;
      refreshing.value = true;
      try {
        await fetchTaskDetail(taskId);
        uni.showToast({ title: '刷新成功', icon: 'success' });
      } catch (err) {
        uni.showToast({ title: '刷新失败', icon: 'none' });
      } finally {
        refreshing.value = false;
      }
    };
    const fetchApplyCompletePreview = async () => {
      previewError.value = '';
      previewLoading.value = true;
      completePreview.value = null;
      try {
        const token = uni.getStorageSync('accessToken');
        if (!token) throw new Error('请先登录');
        const taskIdVal = taskData.value?.taskId || task.value?.taskId;
        if (!taskIdVal) throw new Error('任务 ID 缺失');
        // 使用新的详情接口
        const tryUrls = [
          `${NETWORK_CONFIG.API_BASE_URL}/message/applycomplete/detail?taskId=${taskIdVal}`
        ];
        let data = null;
        for (let i = 0; i < tryUrls.length; i++) {
          const res = await uni.request({
            url: tryUrls[i],
            method: 'GET',
            header: { 'Access-Token': `Bearer ${token}` },
            timeout: 8000
          });
          if (res.statusCode === 200 && res.data) {
            data = res.data;
            break;
          }
        }
        if (!data) throw new Error('未获取到申请完成详情');
        
        // 获取所有贡献者的UID
        const contributorUids = [];
        if (Array.isArray(data.badges)) {
          data.badges.forEach(badge => {
            if (Array.isArray(badge.contributors)) {
              badge.contributors.forEach(contributor => {
                if (contributor.uid) {
                  contributorUids.push(contributor.uid);
                }
              });
            }
          });
        }
        
        // 批量获取用户信息
        if (contributorUids.length > 0) {
          await fetchUsersInfo(contributorUids);
        }
        
        // 兼容字段：proof、badges[{ badgeId, contributors[], association/assoc, level }]、messageId
        completePreview.value = {
          proof: data.proof || data.reason || data.description || '',
          badges: Array.isArray(data.badges) ? data.badges : [],
          messageId: data.messageId,
          taskId: data.taskId,
          createTime: data.createTime,
          status: data.status
        };
      } catch (e) {
        previewError.value = e.message || '加载失败';
      } finally {
        previewLoading.value = false;
      }
    };
    const viewApplyCompleteInfo = async () => {
      showCompletePreview.value = true;
      await fetchApplyCompletePreview();
    };
    const closeCompletePreview = () => {
      showCompletePreview.value = false;
    };
    
    // 获取用户信息
    const fetchUserInfo = async (uid) => {
      if (userInfoCache.value[uid]) {
        return userInfoCache.value[uid];
      }
      
      try {
        const token = uni.getStorageSync('accessToken');
        const response = await uni.request({
          url: `${NETWORK_CONFIG.API_BASE_URL}/user/info`,
          method: 'POST',
          header: { 
            'Access-Token': `Bearer ${token}`,
            'Content-Type': 'application/json'
          },
          data: { uid: uid }
        });
        
        if (response.statusCode === 200 && response.data) {
          userInfoCache.value[uid] = response.data;
          return response.data;
        }
      } catch (error) {
        console.error('获取用户信息失败:', error);
      }
      
      return null;
    };
    
    // 批量获取用户信息
    const fetchUsersInfo = async (uids) => {
      const promises = uids.map(uid => fetchUserInfo(uid));
      await Promise.all(promises);
    };
    
    
    // 获取安全的用户头像（带错误处理）
    const getSafeUserAvatar = (uid) => {
      const userInfo = userInfoCache.value[uid];
      if (userInfo?.avatarUrl) {
        return getAvatarDisplayUrl(userInfo.avatarUrl)
      }
      return '/static/images/default-avatar.png';
    };
    
    // 获取用户昵称
    const getUserName = (uid) => {
      const userInfo = userInfoCache.value[uid];
      return userInfo?.nickname || `用户${uid}`;
    };
    
    // 头像加载错误处理
    const handleAvatarError = (e) => {
      console.log('头像加载失败:', e);
      // 可以在这里设置默认头像
      e.target.src = '/static/images/default-avatar.png';
    };
    
    // 任务发布者头像错误处理
    const handleTaskAvatarError = () => {
      console.log('任务发布者头像加载失败，使用默认头像');
    };
    
    // 组队相关方法
    
    // 选择挑战类型（现在只支持团队类型）
    const selectChallengeType = (type) => {
      // 强制设置为团队类型（所有挑战都通过团队实现）
      challengeType.value = 'team';
      console.log('选择挑战类型:', 'team (所有挑战都通过团队实现)');
      
      // 启用组队模式
        teamMode.value = true;
        // 检查现有团队
        checkExistingTeam();
    };
    
    // 选择团队角色
    const selectTeamRole = (role) => {
      teamRole.value = role;
      console.log('选择团队角色:', role);
      
      if (role === 'leader') {
        // 如果选择队长，检查或创建团队
        if (!teamInfo.value) {
          createTeamImmediately();
        }
        isTeamLeader.value = true;
      } else {
        // 如果选择队员，不自动创建团队
        isTeamLeader.value = false;
      }
    };
    
    // 切换组队模式（保持向后兼容）
    const toggleTeamMode = async (e) => {
      console.log('Checkbox click event:', e);
      console.log('切换前 teamMode:', teamMode.value);
      
      if (teamMode.value) {
        // 当前是开启状态，用户要关闭
        teamMode.value = false;
        isTeamLeader.value = false;
        teamInfo.value = null;
        challengeType.value = 'team'; // 所有挑战都通过团队实现
        console.log('关闭组队模式，重置队长状态（但仍使用团队挑战）');
      } else {
        // 当前是关闭状态，用户要开启
        teamMode.value = true;
        challengeType.value = 'team';
        console.log('启用组队模式，开始检查团队状态...');
        
        // 先检查是否已有团队
        await checkExistingTeam();
        
        // 如果检查后没有团队信息，则创建新团队
        if (!teamInfo.value) {
          console.log('检查后没有团队信息，创建新团队');
          await createTeamImmediately();
          // 创建团队后，确保组队模式保持开启状态
          teamMode.value = true;
        } else {
          console.log('检查后发现有团队信息，用户角色:', isTeamLeader.value ? '队长' : '队员');
        }
        
        // 确保表单显示
        console.log('组队模式已启用，表单应该显示');
      }
    };
    
    // 立即创建团队
    const createTeamImmediately = async () => {
      try {
        const token = uni.getStorageSync('accessToken');
        const currentUser = uni.getStorageSync('userInfo');
        
        if (!token) {
          uni.showToast({ title: '请先登录', icon: 'none' });
          return;
        }
        
        let leaderId = null;
        if (currentUser && currentUser.uid) {
          leaderId = currentUser.uid;
        } else {
          try {
            const tokenPayload = parseJwtToken(token);
            if (tokenPayload) {
              leaderId = tokenPayload.uid || tokenPayload.sub;
            }
          } catch (tokenError) {
            console.error('解析token失败:', tokenError);
            uni.showToast({ title: '用户信息获取失败，请重新登录', icon: 'none' });
            return;
          }
        }
        
        if (!leaderId) {
          uni.showToast({ title: '用户信息获取失败，请重新登录', icon: 'none' });
          return;
        }
        
        console.log('立即创建团队，参数:', {
          taskId: taskData.value?.taskId,
          leaderId: leaderId,
          teamName: teamName.value.trim() || '临时团队'
        });
        
        // 创建团队
        const response = await uni.request({
          url: `${NETWORK_CONFIG.API_BASE_URL}/team/create-invitation`,
          method: 'POST',
          data: {
            taskId: Number(taskData.value?.taskId),
            leaderId: Number(leaderId),
            teamName: teamName.value.trim() || '临时团队',
            inviteeIds: [] // 暂时不邀请任何人，只创建团队
          },
          header: {
            'Access-Token': `Bearer ${token}`,
            'Content-Type': 'application/json'
          }
        });
        
        console.log('团队创建响应:', response);
        
        if (response.data && response.data.success) {
          // 根据是否已存在显示不同消息
          if (response.data.isExisting) {
            uni.showToast({ title: '团队已存在', icon: 'success' });
          } else {
            uni.showToast({ title: '已为您创建团队', icon: 'success' });
          }
          
          // 完全刷新团队信息（会自动清除并重新初始化 invitedUsers）
          await checkExistingTeam();
          
          // 如果 checkExistingTeam 没有返回团队信息，使用响应中的团队信息
          if (!teamInfo.value && response.data.teamInfo) {
            teamInfo.value = response.data.teamInfo;
            editingTeamName.value = teamInfo.value.teamName || '临时团队';
            
            // 设置队长状态 - 创建团队的用户自动成为队长
            isTeamLeader.value = true;
            console.log('团队信息:', teamInfo.value);
            console.log('设置editingTeamName为:', editingTeamName.value);
            console.log('用户角色: 队长');
            
            // 自动获取团队成员的用户信息
            if (teamInfo.value.members && teamInfo.value.members.length > 0) {
              const memberIds = teamInfo.value.members.map(member => member.userId);
              console.log('获取团队成员信息，memberIds:', memberIds);
              await fetchUsersInfo(memberIds);
              
              // 重新初始化已邀请用户列表（团队成员 + 待处理邀请）
              invitedUsers.value.clear();
              memberIds.forEach(memberId => {
                invitedUsers.value.add(memberId);
              });
              
              // 添加待处理邀请
              if (teamInfo.value.pendingInvitations && teamInfo.value.pendingInvitations.length > 0) {
                teamInfo.value.pendingInvitations.forEach(invitation => {
                  if (invitation.userId) {
                    invitedUsers.value.add(invitation.userId);
                  }
                });
              }
              
              console.log('初始化已邀请用户列表（团队成员 + 待处理邀请）:', Array.from(invitedUsers.value));
            }
          }
        } else {
          // 处理团队已存在的情况
          if (response.data?.message && response.data.message.includes('团队已存在')) {
            uni.showToast({ title: '团队已存在，正在加载团队信息...', icon: 'none' });
            // 重新检查团队信息
            await checkExistingTeam();
          } else {
            uni.showToast({ title: response.data?.message || '团队创建失败', icon: 'none' });
          }
        }
      } catch (error) {
        console.error('创建团队失败:', error);
        // 如果是重复创建错误，尝试重新检查团队信息
        if (error.message && error.message.includes('团队已存在')) {
          uni.showToast({ title: '团队已存在，正在加载团队信息...', icon: 'none' });
          await checkExistingTeam();
        } else {
          uni.showToast({ title: '创建团队失败', icon: 'none' });
        }
      }
    };
    
    // 检查现有团队
    const checkExistingTeam = async () => {
      try {
        const token = uni.getStorageSync('accessToken');
        if (!token) return;
        
        const taskIdVal = taskData.value?.taskId || task.value?.taskId;
        if (!taskIdVal) return;
        
        console.log('检查现有团队，任务ID:', taskIdVal);
        
        // 获取当前用户ID
        const currentUser = uni.getStorageSync('userInfo');
        let leaderId = null;
        if (currentUser && currentUser.uid) {
          leaderId = currentUser.uid;
        } else {
          try {
            const tokenPayload = parseJwtToken(token);
            if (tokenPayload) {
              leaderId = tokenPayload.uid || tokenPayload.sub;
            }
          } catch (tokenError) {
            console.error('解析token失败:', tokenError);
            return;
          }
        }
        
        if (!leaderId) return;
        
        // 调用后端API检查是否已有团队
        const response = await uni.request({
          url: `${NETWORK_CONFIG.API_BASE_URL}/team/info?taskId=${taskIdVal}&userId=${leaderId}`,
          method: 'GET',
          header: {
            'Access-Token': `Bearer ${token}`
          }
        });
        
        console.log('检查团队信息响应:', response);
        
        if (response.statusCode === 200 && response.data && response.data.success) {
          if (response.data.teamInfo) {
            // 有团队信息，设置组队模式为true
            teamMode.value = true;
            teamInfo.value = response.data.teamInfo;
            editingTeamName.value = teamInfo.value.teamName || '临时团队';
            
            // 判断用户是否是队长
            console.log('团队信息:', teamInfo.value);
            console.log('teamInfo.leaderId:', teamInfo.value.leaderId, '类型:', typeof teamInfo.value.leaderId);
            console.log('当前用户ID:', leaderId, '类型:', typeof leaderId);
            console.log('严格相等比较:', teamInfo.value.leaderId === leaderId);
            console.log('宽松相等比较:', teamInfo.value.leaderId == leaderId);
            
            // 使用字符串比较确保类型一致
            isTeamLeader.value = String(teamInfo.value.leaderId) === String(leaderId);
            console.log('checkExistingTeam - 发现现有团队，启用组队模式:', teamInfo.value);
            console.log('checkExistingTeam - teamInfo.leaderId:', teamInfo.value.leaderId, 'leaderId:', leaderId);
            console.log('checkExistingTeam - 设置isTeamLeader:', isTeamLeader.value);
            console.log('checkExistingTeam - 用户角色:', isTeamLeader.value ? '队长' : '队员');
            
            // 检查团队状态，如果是已解散状态(status=2)，显示解散提示
            if (teamInfo.value.status === 2) {
              console.log('团队已解散，显示解散提示');
              // 已解散的团队仍然显示，但UI会显示解散状态
            }
            
            // 同步 activeVotes 到 activeTeamVotes（从团队信息中获取）
            if (teamInfo.value.activeVotes && Array.isArray(teamInfo.value.activeVotes)) {
              activeTeamVotes.value = teamInfo.value.activeVotes;
              console.log('✅ 从 teamInfo 同步 activeVotes 到 activeTeamVotes，数量:', activeTeamVotes.value.length);
              activeTeamVotes.value.forEach((vote, index) => {
                console.log(`  投票 ${index + 1}:`, {
                  voteId: vote.voteId,
                  id: vote.id,
                  messageId: vote.messageId,
                  voteType: vote.voteType,
                  hasVoted: vote.hasVoted
                });
              });
            } else {
              console.log('⚠️ teamInfo.activeVotes 不存在或不是数组');
            }
            
            // 如果 activeVotes 为空，尝试通过 loadTeamVotes 加载
            if (!activeTeamVotes.value || activeTeamVotes.value.length === 0) {
              console.log('🔄 activeTeamVotes 为空，尝试通过 loadTeamVotes 加载');
              if (teamInfo.value.teamId) {
                await loadTeamVotes(teamInfo.value.teamId);
              }
            }
            
            // 获取团队成员的用户信息
            if (teamInfo.value.members && teamInfo.value.members.length > 0) {
              const memberIds = teamInfo.value.members.map(member => member.userId);
              console.log('获取现有团队成员信息，memberIds:', memberIds);
              await fetchUsersInfo(memberIds);
              
              // 清除旧的 invitedUsers，重新初始化已邀请用户列表
              // 将现有团队成员标记为已邀请
              invitedUsers.value.clear();
              memberIds.forEach(memberId => {
                invitedUsers.value.add(memberId);
              });
              
              // 将待处理邀请的用户也标记为已邀请
              if (teamInfo.value.pendingInvitations && teamInfo.value.pendingInvitations.length > 0) {
                teamInfo.value.pendingInvitations.forEach(invitation => {
                  if (invitation.userId) {
                    invitedUsers.value.add(invitation.userId);
                  }
                });
                console.log('添加待处理邀请到已邀请列表');
              }
              
              console.log('初始化已邀请用户列表（团队成员 + 待处理邀请）:', Array.from(invitedUsers.value));
            } else {
              // 如果没有成员，清除 invitedUsers，但保留待处理邀请
              invitedUsers.value.clear();
              
              // 如果有待处理邀请，仍然要添加
              if (teamInfo.value.pendingInvitations && teamInfo.value.pendingInvitations.length > 0) {
                teamInfo.value.pendingInvitations.forEach(invitation => {
                  if (invitation.userId) {
                    invitedUsers.value.add(invitation.userId);
                  }
                });
                console.log('团队没有成员，但有待处理邀请:', Array.from(invitedUsers.value));
              } else {
                console.log('团队没有成员也没有待处理邀请，清除已邀请用户列表');
              }
            }
          } else {
            // 没有团队信息，保持组队模式为false
            teamMode.value = false;
            isTeamLeader.value = false;
            console.log('没有现有团队，保持个人模式');
          }
        } else {
          // API调用失败，保持默认状态
          teamMode.value = false;
          isTeamLeader.value = false;
          console.log('检查团队信息失败，保持个人模式');
        }
      } catch (error) {
        console.error('检查现有团队失败:', error);
        // 出错时保持默认状态
        teamMode.value = false;
      }
    };
    
    
    // 处理团队申请（新版本）
    const handleTeamApplicationNew = async () => {
      if (!challengeContent.value.trim()) {
        uni.showToast({
          title: '请填写挑战内容',
          icon: 'none'
        });
        return;
      }
      
      if (!teamInfo.value) {
        uni.showToast({
          title: '请先创建团队',
          icon: 'none'
        });
        return;
      }
      
      try {
        const token = uni.getStorageSync('accessToken');
        if (!token) {
          uni.showToast({
            title: '请先登录',
            icon: 'none'
          });
          return;
        }
        
        const requestData = {
          taskId: taskId,
          content: challengeContent.value.trim(),
          challengeType: 'team',
          teamId: teamInfo.value.teamId,
          teamName: teamInfo.value.teamName
        };
        
        const response = await uni.request({
          url: `${NETWORK_CONFIG.API_BASE_URL}/task/apply`,
          method: 'POST',
          header: {
            'Access-Token': `Bearer ${token}`,
            'Content-Type': 'application/json'
          },
          data: requestData
        });
        
        if (response.data.success) {
          uni.showToast({
            title: '团队申请提交成功',
            icon: 'success'
          });
          
          // 刷新页面数据
          await fetchTaskDetail(taskId);
          await checkUserApplicationStatus();
        } else {
          uni.showToast({
            title: response.data.message || '申请失败',
            icon: 'none'
          });
        }
      } catch (error) {
        console.error('申请失败:', error);
        uni.showToast({
          title: '申请失败，请重试',
          icon: 'none'
        });
      }
    };
    
    // 显示联系队长模态框
    const showContactLeaderModal = () => {
      uni.showModal({
        title: '联系队长',
        content: '您可以通过以下方式联系队长：\n1. 在聊天室中发送消息\n2. 通过好友系统添加队长\n3. 查看队长的公开信息',
        showCancel: true,
        cancelText: '取消',
        confirmText: '去聊天室',
        success: (res) => {
          if (res.confirm) {
            // 跳转到聊天室
            uni.navigateTo({
              url: '/pages/chat/index'
            });
          }
        }
      });
    };
    
    // 统一的申请处理方法（现在所有申请都通过团队实现）
    const handleApplication = async () => {
      // 所有申请都通过团队实现
      if (teamMode.value) {
        await handleTeamApplication();
      } else {
        await handleTeamApplicationNew();
      }
    };
    
    // 组队申请处理
    const handleTeamApplication = async () => {
      try {
        // 团队已经在勾选时创建了，现在只需要进行个人申请
        if (teamInfo.value) {
          await applyForTask();
        } else {
          uni.showToast({ title: '团队信息不存在，请重新勾选组队申请', icon: 'none' });
        }
      } catch (error) {
        console.error('组队申请失败:', error);
        uni.showToast({ title: '组队申请失败', icon: 'none' });
      }
    };
    
    // 从TeamInvitationModal复制的方法
    const getTeamStatusText = (status) => {
      if (status === null || status === undefined) {
        return '未知状态'
      }
      switch (status) {
        case 0: return '组建中'
        case 1: return '已组建'
        case 2: return '已解散'
        default: return '未知状态'
      }
    };
    
    const formatTime = (timeStr) => {
      if (!timeStr) return ''
      const date = new Date(timeStr)
      const now = new Date()
      const diff = now - date
      
      if (diff < 60000) return '刚刚'
      if (diff < 3600000) return Math.floor(diff / 60000) + '分钟前'
      if (diff < 86400000) return Math.floor(diff / 3600000) + '小时前'
      return Math.floor(diff / 86400000) + '天前'
    };
    
    // 获取用户信息
    const getUserInfo = async (userId) => {
      if (userInfoCache.value[userId]) {
        return userInfoCache.value[userId]
      }
      
      try {
        const token = uni.getStorageSync('accessToken')
        if (!token) return null
        
        console.log('获取用户信息，userId:', userId)
        
        const response = await uni.request({
          url: `${NETWORK_CONFIG.API_BASE_URL}/user/info`,
          method: 'POST',
          data: {
            uid: userId
          },
          header: {
            'Access-Token': `Bearer ${token}`,
            'Content-Type': 'application/json'
          }
        })
        
        console.log('用户信息响应:', response)
        
        if (response.statusCode === 200 && response.data) {
          const userInfo = response.data
          userInfoCache.value[userId] = userInfo
          console.log('用户信息缓存成功:', userInfo)
          return userInfo
        } else {
          console.error('获取用户信息失败，响应:', response.data)
        }
      } catch (error) {
        console.error('获取用户信息失败:', error)
      }
      
      return null
    };
    
    // 获取用户昵称
    const getUserNickname = (userId) => {
      const userInfo = userInfoCache.value[userId]
      return userInfo ? userInfo.nickname : '加载中...'
    };
    
    // 获取投票规则文本（支持两种调用方式：对象参数或单独参数）
    const getVoteRuleText = (voteOrVoteType, requiredVotes, totalVoters) => {
      // 判断是对象参数还是单独参数
      let voteType, reqVotes, totalVts;
      
      if (typeof voteOrVoteType === 'object' && voteOrVoteType !== null) {
        // 对象参数模式：getVoteRuleText(vote)
        const vote = voteOrVoteType;
        voteType = vote.voteType;
        reqVotes = vote.requiredVotes;
        totalVts = vote.totalVoters;
        
        // 对于踢人投票和退出投票，根据队长是否投同意显示不同的规则
        if (voteType === 1) { // REMOVE_MEMBER 类型（踢人投票或退出投票）
          const isLeaveVote = vote.initiatorId && vote.targetUserId && vote.initiatorId === vote.targetUserId;
          
          if (vote.leaderApproved === true) {
            // 队长投同意：>=50%即可通过（等于50%也可以）
            return `需要${reqVotes || 0}票通过（队长已投同意，≥50%即可通过）`;
          } else if (vote.leaderApproved === false) {
            // 队长投反对或不投票：必须>50%才能通过（不能等于50%）
            return `需要超过${reqVotes || 0}票通过（队长未同意，必须>50%）`;
          } else {
            // 队长状态未知（队长还没投票），显示两种情况
            return `需要${reqVotes || 0}票通过（队长投同意≥50%即可，否则需>50%）`;
          }
        }
      } else {
        // 单独参数模式：getVoteRuleText(voteType, requiredVotes, totalVoters)
        voteType = voteOrVoteType;
        reqVotes = requiredVotes;
        totalVts = totalVoters;
      }
      
      // 通用规则文本
      if (voteType === 1) {
        return `需要${reqVotes || 0}票同意（共${totalVts || 0}人，需≥50%）`;
      } else if (voteType === 2) {
        return `需要${reqVotes || 0}票同意（共${totalVts || 0}人，需≥2/3）`;
      } else if (voteType === 3) {
        // 选举投票：需要超过50%参与，然后候选人需要超过50%的选票
        return `需要${reqVotes || 0}人参与投票（共${totalVts || 0}人，需>50%）`;
      } else if (voteType) {
        // 其他投票类型
        return `需要${reqVotes || 0}票通过`;
      }
      return '';
    };
    
    // 获取用户头像
    const getUserAvatar = (userId) => {
      const userInfo = userInfoCache.value[userId]
      console.log('获取用户头像，userId:', userId, 'userInfo:', userInfo)
      
      if (userInfo && userInfo.avatarUrl) {
        return getAvatarDisplayUrl(userInfo.avatarUrl)
      }
      
      console.log('使用默认头像')
      return '/static/images/default-avatar.png'
    };
    
    // 搜索好友
    const searchFriends = async () => {
      if (!searchKeyword.value.trim()) {
        searchResults.value = []
        return
      }
      
      // 如果团队已解散，不允许搜索
      if (teamInfo.value && teamInfo.value.status === 2) {
        uni.showToast({ title: '团队已解散，无法邀请成员', icon: 'none' })
        return
      }
      
      searchLoading.value = true
      searchError.value = null
      
      try {
        const token = uni.getStorageSync('accessToken')
        const response = await uni.request({
          url: `${NETWORK_CONFIG.API_BASE_URL}/friends/search?keyword=${encodeURIComponent(searchKeyword.value)}`,
          method: 'GET',
          header: {
            'Access-Token': `Bearer ${token}`
          }
        })
        
        if (response.data && response.data.code === 200) {
          const allResults = response.data.data || []
          searchResults.value = allResults.sort((a, b) => {
            if (a.friendStatus === 'accepted' && b.friendStatus !== 'accepted') return -1
            if (a.friendStatus !== 'accepted' && b.friendStatus === 'accepted') return 1
            return 0
          })
        } else {
          searchError.value = response.data?.message || '搜索失败'
        }
      } catch (error) {
        console.error('搜索好友失败:', error)
        searchError.value = '搜索失败，请重试'
      } finally {
        searchLoading.value = false
      }
    };
    
    
    
    
    // 邀请单个用户
    const inviteSingleUser = async (friendId) => {
      try {
        const token = uni.getStorageSync('accessToken')
        const currentUser = uni.getStorageSync('userInfo')
        
        let leaderId = null
        if (currentUser && currentUser.uid) {
          leaderId = currentUser.uid
        } else {
          try {
            const tokenPayload = parseJwtToken(token)
            leaderId = tokenPayload.uid || tokenPayload.sub
          } catch (tokenError) {
            console.error('解析token失败:', tokenError)
            return
          }
        }
        
        if (!leaderId) return
        
        // 检查是否尝试邀请自己
        if (String(leaderId) === String(friendId)) {
          uni.showToast({ title: '不能邀请自己加入团队', icon: 'none' })
          return
        }
        
        // 检查是否尝试邀请任务发布者
        if (taskData.value?.publisherId && String(taskData.value.publisherId) === String(friendId)) {
          uni.showToast({ title: '不能邀请任务发布者加入团队', icon: 'none' })
          return
        }
        
        const response = await uni.request({
          url: `${NETWORK_CONFIG.API_BASE_URL}/team/send-invitation`,
          method: 'POST',
          data: {
            taskId: Number(taskData.value?.taskId),
            leaderId: Number(leaderId),
            teamName: teamName.value.trim() || '临时团队',
            inviteeIds: [Number(friendId)]
          },
          header: {
            'Access-Token': `Bearer ${token}`,
            'Content-Type': 'application/json'
          }
        })
        
        if (response.data && response.data.success) {
          uni.showToast({
            title: '邀请发送成功',
            icon: 'success'
          })
          markUserAsInvited(friendId)
        } else {
          uni.showToast({
            title: response.data?.message || '发送邀请失败',
            icon: 'none'
          })
        }
      } catch (error) {
        console.error('发送邀请失败:', error)
        uni.showToast({
          title: '发送邀请失败',
          icon: 'none'
        })
      }
    };
    
    // 标记用户已邀请
    const markUserAsInvited = (friendId) => {
      invitedUsers.value.add(friendId)
    };
    
    const isUserInvited = (friendId) => {
      return invitedUsers.value.has(friendId)
    };
    
    // 处理团队名称输入
    const handleTeamNameInput = (e) => {
      console.log('团队名称输入事件:', e);
      console.log('输入值:', e.detail?.value || e.target?.value);
      console.log('editingTeamName当前值:', editingTeamName.value);
    };
    
    // 处理团队名称聚焦
    const handleTeamNameFocus = (e) => {
      console.log('团队名称输入框聚焦:', e);
      console.log('editingTeamName当前值:', editingTeamName.value);
    };
    
    // 测试设置团队名称
    const testSetTeamName = () => {
      console.log('测试设置团队名称');
      editingTeamName.value = '测试团队名称';
      console.log('设置后editingTeamName:', editingTeamName.value);
      uni.showToast({ title: '已设置测试团队名称', icon: 'success' });
    };
    
    // 保存团队名称
    const saveTeamName = async () => {
      if (!editingTeamName.value.trim()) {
        uni.showToast({ title: '请输入团队名称', icon: 'none' })
        return
      }
      
      if (!teamInfo.value || !teamInfo.value.teamId) {
        uni.showToast({ title: '团队信息不存在', icon: 'none' })
        return
      }
      
      try {
        const token = uni.getStorageSync('accessToken')
        if (!token) {
          uni.showToast({ title: '请先登录', icon: 'none' })
          return
        }
        
        console.log('更新团队名称，参数:', {
          teamId: teamInfo.value.teamId,
          teamName: editingTeamName.value.trim()
        });
        
        const response = await uni.request({
          url: `${NETWORK_CONFIG.API_BASE_URL}/team/update-name`,
          method: 'POST',
          data: {
            teamId: Number(teamInfo.value.teamId),
            teamName: editingTeamName.value.trim()
          },
          header: {
            'Access-Token': `Bearer ${token}`,
            'Content-Type': 'application/json'
          }
        })
        
        console.log('更新团队名称响应:', response);
        
        if (response.data && response.data.success) {
          uni.showToast({ title: '团队名称更新成功', icon: 'success' })
          if (teamInfo.value) {
            teamInfo.value.teamName = editingTeamName.value.trim()
          }
        } else {
          uni.showToast({ title: response.data?.message || '更新失败', icon: 'none' })
        }
      } catch (error) {
        console.error('更新团队名称失败:', error)
        uni.showToast({ title: '更新团队名称失败', icon: 'none' })
      }
    };
    
    // 队长踢出队员
    const removeTeamMember = async (memberId) => {
      if (!teamInfo.value || !teamInfo.value.teamId) {
        uni.showToast({ title: '团队信息不存在', icon: 'none' })
        return
      }
      
      try {
        const token = uni.getStorageSync('accessToken')
        if (!token) {
          uni.showToast({ title: '请先登录', icon: 'none' })
          return
        }
        
        const currentUser = uni.getStorageSync('userInfo')
        let leaderId = null
        if (currentUser && currentUser.uid) {
          leaderId = currentUser.uid
        } else {
          try {
            const tokenPayload = parseJwtToken(token)
            leaderId = tokenPayload.uid || tokenPayload.sub
          } catch (tokenError) {
            console.error('解析token失败:', tokenError)
            uni.showToast({ title: '用户信息获取失败，请重新登录', icon: 'none' })
            return
          }
        }
        
        if (!leaderId) {
          uni.showToast({ title: '用户信息获取失败，请重新登录', icon: 'none' })
          return
        }
        
        console.log('踢出队员，参数:', {
          teamId: teamInfo.value.teamId,
          leaderId: leaderId,
          memberId: memberId
        })
        
        const response = await uni.request({
          url: `${NETWORK_CONFIG.API_BASE_URL}/team/remove-member`,
          method: 'POST',
          data: {
            teamId: teamInfo.value.teamId,
            leaderId: leaderId,
            memberId: memberId
          },
          header: {
            'Access-Token': `Bearer ${token}`,
            'Content-Type': 'application/json'
          }
        })
        
        console.log('踢出队员响应:', response)
        
        if (response.data && response.data.success) {
          uni.showToast({ title: '队员移除成功', icon: 'success' })
          // 重新加载团队信息
          await checkExistingTeam()
        } else {
          uni.showToast({ title: response.data?.message || '移除失败', icon: 'none' })
        }
      } catch (error) {
        console.error('踢出队员失败:', error)
        uni.showToast({ title: '踢出队员失败', icon: 'none' })
      }
    }
    
    // 发起踢人投票
    const initiateRemoveMemberVote = async (memberId) => {
      if (!teamInfo.value || !teamInfo.value.teamId) {
        uni.showToast({ title: '团队信息不存在', icon: 'none' })
        return
      }
      
      // 显示输入原因的弹窗
      uni.showModal({
        title: '发起踢人投票',
        content: '请输入踢人原因',
        editable: true,
        placeholderText: '请输入踢人原因...',
        success: async (res) => {
          if (res.confirm && res.content) {
            try {
              const token = uni.getStorageSync('accessToken')
              if (!token) {
                uni.showToast({ title: '请先登录', icon: 'none' })
                return
              }
              
              const currentUser = uni.getStorageSync('userInfo')
              let initiatorId = null
              if (currentUser && currentUser.uid) {
                initiatorId = currentUser.uid
              } else {
                try {
                  const tokenPayload = parseJwtToken(token)
                  initiatorId = tokenPayload.uid || tokenPayload.sub
                } catch (tokenError) {
                  console.error('解析token失败:', tokenError)
                  uni.showToast({ title: '用户信息获取失败，请重新登录', icon: 'none' })
                  return
                }
              }
              
              if (!initiatorId) {
                uni.showToast({ title: '用户信息获取失败，请重新登录', icon: 'none' })
                return
              }
              
              const response = await uni.request({
                url: `${NETWORK_CONFIG.API_BASE_URL}/team-vote/initiate-remove-member`,
                method: 'POST',
                data: {
                  teamId: teamInfo.value.teamId,
                  initiatorId: initiatorId,
                  targetUserId: memberId,
                  reason: res.content
                },
                header: {
                  'Access-Token': `Bearer ${token}`,
                  'Content-Type': 'application/json'
                }
              })
              
              if (response.data && response.data.success) {
                uni.showToast({ title: '踢人投票已发起', icon: 'success' })
                // 重新加载团队信息（会自动清除并更新 invitedUsers）
                await checkExistingTeam();
                // 重新加载投票信息
                if (teamInfo.value?.teamId) {
                  await loadTeamVotes(teamInfo.value.teamId);
                }
              } else {
                uni.showToast({ title: response.data?.message || '发起投票失败', icon: 'none' })
              }
            } catch (error) {
              console.error('发起踢人投票失败:', error)
              uni.showToast({ title: '操作失败，请重试', icon: 'none' })
            }
          }
        }
      })
    }
    
    // 参与投票 - 通过 messageId 投票（用于旧版兼容）
    const voteOnProposal = async (voteId, approve) => {
      try {
        const token = uni.getStorageSync('accessToken')
        if (!token) {
          uni.showToast({ title: '请先登录', icon: 'none' })
          return
        }
        
        console.log('🔵 voteOnProposal 调用开始');
        console.log('  - voteId:', voteId, '类型:', typeof voteId);
        console.log('  - approve:', approve);
        console.log('  - activeTeamVotes 数量:', activeTeamVotes.value?.length || 0);
        console.log('  - activeTeamVotes 内容:', activeTeamVotes.value);
        console.log('  - teamInfo.activeVotes 数量:', teamInfo.value?.activeVotes?.length || 0);
        console.log('  - teamInfo.activeVotes 内容:', teamInfo.value?.activeVotes);
        
        let vote = null;
        let messageId = null;
        
        // 1. 首先尝试从 activeTeamVotes 中查找
        if (activeTeamVotes.value && activeTeamVotes.value.length > 0) {
          vote = activeTeamVotes.value.find(v => {
            const match = (v.voteId === voteId || v.id === voteId || String(v.voteId) === String(voteId) || String(v.id) === String(voteId));
            if (match) {
              console.log('✅ 在 activeTeamVotes 中找到匹配的投票:', v);
            }
            return match;
          });
          
          if (vote) {
            messageId = vote.messageId;
            console.log('✅ 从 activeTeamVotes 中获取的 messageId:', messageId);
          }
        }
        
        // 2. 如果 activeTeamVotes 中没找到，尝试从 teamInfo.activeVotes 中查找
        if (!vote && teamInfo.value?.activeVotes && teamInfo.value.activeVotes.length > 0) {
          console.log('⚠️ activeTeamVotes 中未找到，尝试从 teamInfo.activeVotes 中查找...');
          vote = teamInfo.value.activeVotes.find(v => {
            const match = (v.voteId === voteId || v.id === voteId || String(v.voteId) === String(voteId) || String(v.id) === String(voteId));
            if (match) {
              console.log('✅ 在 teamInfo.activeVotes 中找到匹配的投票:', v);
            }
            return match;
          });
          
          if (vote) {
            messageId = vote.messageId;
            console.log('✅ 从 teamInfo.activeVotes 中获取的 messageId:', messageId);
          }
        }
        
        // 3. 如果本地没找到 messageId，直接通过后端接口查询（用户要求：点击时再去查找）
        if (!messageId && voteId) {
          console.log('🔄 本地数据源未找到 messageId，直接通过 voteId 调用后端接口查询...');
          try {
            console.log('  - 调用接口: /message/get-by-vote');
            console.log('  - 参数 voteId:', voteId);
            
            const messageResponse = await uni.request({
              url: `${NETWORK_CONFIG.API_BASE_URL}/message/get-by-vote?voteId=${voteId}`,
              method: 'GET',
              header: { 'Access-Token': `Bearer ${token}` }
            });
            
            console.log('📥 精准接口响应状态码:', messageResponse.statusCode);
            console.log('📥 精准接口响应数据:', messageResponse.data);
            
            if (messageResponse.statusCode === 200 && messageResponse.data?.success) {
              if (messageResponse.data.messageId) {
                messageId = messageResponse.data.messageId;
                console.log('✅ 通过精准接口找到对应的 messageId:', messageId);
                
                // 更新 vote 对象的 messageId（如果存在）
                if (vote) {
                  vote.messageId = messageId;
                  console.log('✅ 已更新 vote 对象的 messageId');
                }
              } else {
                console.warn('⚠️ 接口返回成功但无 messageId，响应:', messageResponse.data);
              }
            } else {
              console.warn('⚠️ 精准接口查询失败，状态码:', messageResponse.statusCode, '响应:', messageResponse.data);
            }
          } catch (msgError) {
            console.error('❌ 通过精准接口查询 messageId 失败:', msgError);
            console.error('  - 错误类型:', msgError.constructor?.name);
            console.error('  - 错误消息:', msgError.message);
            if (msgError.data) {
              console.error('  - 错误数据:', msgError.data);
            }
          }
        }
        
        // 4. 如果仍然没有 messageId，报错
        if (!messageId) {
          console.error('❌ 最终未找到 messageId');
          console.error('  - voteId:', voteId);
          console.error('  - vote 对象:', vote);
          console.error('  - activeTeamVotes:', activeTeamVotes.value);
          console.error('  - teamInfo.activeVotes:', teamInfo.value?.activeVotes);
          uni.showToast({ title: '未找到投票消息，请通过消息中心投票', icon: 'none' });
          return;
        }
        
        console.log('✅ 最终找到 messageId:', messageId);
        
        // 转换投票选择为数字格式
        const voteChoice = approve ? 1 : 2; // 1=同意, 2=反对
        
        console.log('提交投票参数:', {
          messageId: messageId,
          voteChoice,
          voteReason: ''
        });
        
        const response = await uni.request({
          url: `${NETWORK_CONFIG.API_BASE_URL}/message/vote`,
          method: 'POST',
          data: {
            messageId: messageId,
            voteChoice: voteChoice,
            voteReason: ''
          },
          header: {
            'Access-Token': `Bearer ${token}`,
            'Content-Type': 'application/json'
          }
        })
        
        // 解析响应数据
        let responseData;
        if (typeof response.data === 'string') {
          try {
            responseData = JSON.parse(response.data);
          } catch (e) {
            console.error('解析响应数据失败:', e);
            responseData = { success: false, message: '响应数据格式错误' };
          }
        } else {
          responseData = response.data;
        }
        
        console.log('投票响应:', responseData);
        
        if (responseData && responseData.success) {
          uni.showToast({ 
            title: approve ? '已投票同意' : '已投票反对', 
            icon: 'success' 
          })
          // 重新加载团队信息
          await checkExistingTeam()
          
          // 重新加载投票数据
          if (teamInfo.value?.teamId) {
            await loadTeamVotes(teamInfo.value.teamId);
          }
        } else {
          uni.showToast({ title: responseData?.message || '投票失败', icon: 'none' })
        }
      } catch (error) {
        console.error('投票失败:', error)
        uni.showToast({ title: '操作失败，请重试', icon: 'none' })
      }
    }
    
    // 提交投票（任务详情页面使用）- 通过 messageId 投票
    const submitVote = async (voteId, voteChoice) => {
      try {
        voteLoading.value = true;
        const token = uni.getStorageSync('accessToken');
        if (!token) {
          uni.showToast({ title: '请先登录', icon: 'none' });
          return;
        }
        
        // 从 activeTeamVotes 中查找对应的投票，获取 messageId
        let vote = activeTeamVotes.value.find(v => v.voteId === voteId || v.id === voteId);
        let messageId = vote?.messageId;
        
        // 如果 activeTeamVotes 中没有 messageId，通过精准接口查询
        if (!messageId && vote && vote.voteId) {
          try {
            console.log('activeTeamVotes 中没有 messageId，尝试通过精准接口查询，voteId:', vote.voteId);
            const messageResponse = await uni.request({
              url: `${NETWORK_CONFIG.API_BASE_URL}/message/get-by-vote`,
              method: 'GET',
              data: {
                voteId: vote.voteId
              },
              header: { 'Access-Token': `Bearer ${token}` }
            });
            
            if (messageResponse.statusCode === 200 && messageResponse.data?.success && messageResponse.data?.messageId) {
              messageId = messageResponse.data.messageId;
              console.log('通过精准接口找到对应的 messageId:', messageId);
            }
          } catch (msgError) {
            console.error('通过精准接口查询 messageId 失败:', msgError);
          }
        }
        
        if (!vote || !messageId) {
          uni.showToast({ title: '未找到投票消息，请通过消息中心投票2', icon: 'none' });
          return;
        }
        
        const response = await uni.request({
          url: `${NETWORK_CONFIG.API_BASE_URL}/message/vote`,
          method: 'POST',
          data: {
            messageId: messageId,
            voteChoice: voteChoice, // 1=同意, 2=反对
            voteReason: ''
          },
          header: {
            'Access-Token': `Bearer ${token}`,
            'Content-Type': 'application/json'
          }
        });
        
        let responseData;
        if (typeof response.data === 'string') {
          try {
            responseData = JSON.parse(response.data);
          } catch (e) {
            responseData = { success: false, message: '响应数据格式错误' };
          }
        } else {
          responseData = response.data;
        }
        
        if (responseData && responseData.success) {
          uni.showToast({ 
            title: voteChoice === 1 ? '已投票同意' : '已投票反对', 
            icon: 'success' 
          });
          
          // 重新加载投票数据
          if (teamInfo.value?.teamId) {
            await loadTeamVotes(teamInfo.value.teamId);
          }
        } else {
          uni.showToast({ title: responseData?.message || '投票失败', icon: 'none' });
        }
      } catch (error) {
        console.error('投票失败:', error);
        uni.showToast({ title: '操作失败，请重试', icon: 'none' });
      } finally {
        voteLoading.value = false;
      }
    };
    
    // 提交候选人投票（选举投票）- 通过 messageId 投票
    const submitCandidateVote = async (voteId, candidateId) => {
      try {
        voteLoading.value = true;
        const token = uni.getStorageSync('accessToken');
        if (!token) {
          uni.showToast({ title: '请先登录', icon: 'none' });
          return;
        }
        
        // 从 activeTeamVotes 中查找对应的投票，获取 messageId
        let vote = activeTeamVotes.value.find(v => v.voteId === voteId || v.id === voteId);
        let messageId = vote?.messageId;
        
        // 如果 activeTeamVotes 中没有 messageId，通过精准接口查询
        if (!messageId && vote && vote.voteId) {
          try {
            console.log('activeTeamVotes 中没有 messageId，尝试通过精准接口查询，voteId:', vote.voteId);
            const messageResponse = await uni.request({
              url: `${NETWORK_CONFIG.API_BASE_URL}/message/get-by-vote`,
              method: 'GET',
              data: {
                voteId: vote.voteId
              },
              header: { 'Access-Token': `Bearer ${token}` }
            });
            
            if (messageResponse.statusCode === 200 && messageResponse.data?.success && messageResponse.data?.messageId) {
              messageId = messageResponse.data.messageId;
              console.log('通过精准接口找到对应的 messageId:', messageId);
            }
          } catch (msgError) {
            console.error('通过精准接口查询 messageId 失败:', msgError);
          }
        }
        
        if (!vote || !messageId) {
          uni.showToast({ title: '未找到投票消息，请通过消息中心投票3', icon: 'none' });
          return;
        }
        
        const response = await uni.request({
          url: `${NETWORK_CONFIG.API_BASE_URL}/message/vote`,
          method: 'POST',
          data: {
            messageId: messageId,
            voteChoice: 1, // 选举投票统一为同意
            candidateId: candidateId // 候选人ID
          },
          header: {
            'Access-Token': `Bearer ${token}`,
            'Content-Type': 'application/json'
          }
        });
        
        let responseData;
        if (typeof response.data === 'string') {
          try {
            responseData = JSON.parse(response.data);
          } catch (e) {
            responseData = { success: false, message: '响应数据格式错误' };
          }
        } else {
          responseData = response.data;
        }
        
        if (responseData && responseData.success) {
          uni.showToast({ title: '投票成功', icon: 'success' });
          selectedCandidateId.value = null; // 重置选择
          
          // 重新加载投票数据
          if (teamInfo.value?.teamId) {
            await loadTeamVotes(teamInfo.value.teamId);
          }
        } else {
          uni.showToast({ title: responseData?.message || '投票失败', icon: 'none' });
        }
      } catch (error) {
        console.error('投票失败:', error);
        uni.showToast({ title: '操作失败，请重试', icon: 'none' });
      } finally {
        voteLoading.value = false;
      }
    };
    
    // 选择候选人
    const selectCandidate = (candidateId) => {
      selectedCandidateId.value = candidateId === selectedCandidateId.value ? null : candidateId;
    };
    
    // 撤回投票（任务详情页面使用）
    const withdrawVoteFromTask = async (voteId) => {
      await withdrawVote(voteId);
    };
    
    // 格式化倒计时显示
    const formatCountdown = (seconds) => {
      if (!seconds || seconds <= 0) return '00:00:00';
      const hours = Math.floor(seconds / 3600);
      const minutes = Math.floor((seconds % 3600) / 60);
      const secs = seconds % 60;
      return `${hours.toString().padStart(2, '0')}:${minutes.toString().padStart(2, '0')}:${secs.toString().padStart(2, '0')}`;
    };
    
    // 获取投票标题
    const getVoteTitle = (vote) => {
      if (vote.voteTitle) return vote.voteTitle;
      if (vote.voteType === 1) {
        // 检查是否是退出投票
        if (vote.initiatorId && vote.targetUserId && vote.initiatorId === vote.targetUserId) {
          return '退出团队投票';
        }
        return '踢人投票';
      } else if (vote.voteType === 2) {
        return '弹劾队长投票';
      } else if (vote.voteType === 3) {
        return '选举新队长投票';
      }
      return '投票';
    };
    
    // 获取投票类型文本
    const getVoteTypeText = (voteType) => {
      switch (voteType) {
        case 1: return '踢人投票';
        case 2: return '弹劾投票';
        case 3: return '选举投票';
        default: return '投票';
      }
    };
    
    // 获取投票选择文本
    const getVoteChoiceText = (userVote, voteType) => {
      if (voteType === 3) {
        // 选举投票：显示候选人
        return userVote ? '已选择候选人' : '未知';
      } else {
        // 普通投票：同意/反对
        if (userVote === true || userVote === 1) return '同意';
        if (userVote === false || userVote === 2) return '反对';
        return '未知';
      }
    };
    
    // 获取投票状态文本
    const getVoteStatusText = (status) => {
      switch (status) {
        case 0: return '进行中';
        case 1: return '已通过';
        case 2: return '已拒绝';
        case 3: return '已取消';
        case 5: return '已结束';
        default: return '未知';
      }
    };
    
    // 获取投票选择详情文本（用于投票记录）
    const getVoteChoiceDetailText = (voteChoice, voteType) => {
      if (voteType === 3) {
        // 选举投票
        return voteChoice === 1 ? '已投票' : voteChoice === 2 ? '反对' : '弃权';
      } else {
        // 普通投票
        switch (voteChoice) {
          case 1: return '同意';
          case 2: return '反对';
          case 3: return '弃权';
          default: return '未知';
        }
      }
    };
    
    // 撤回投票 - 通过 messageId 撤回
    const withdrawVote = async (voteId) => {
      try {
        withdrawLoading.value = true;
        
        const token = uni.getStorageSync('accessToken');
        if (!token) {
          uni.showToast({ title: '请先登录', icon: 'none' });
          return;
        }
        
        // 从 activeTeamVotes 中查找对应的投票，获取 messageId
        let vote = activeTeamVotes.value.find(v => v.voteId === voteId || v.id === voteId);
        let messageId = vote?.messageId;
        
        // 如果 activeTeamVotes 中没有 messageId，通过精准接口查询
        if (!messageId && vote && vote.voteId) {
          try {
            console.log('activeTeamVotes 中没有 messageId，尝试通过精准接口查询，voteId:', vote.voteId);
            const messageResponse = await uni.request({
              url: `${NETWORK_CONFIG.API_BASE_URL}/message/get-by-vote`,
              method: 'GET',
              data: {
                voteId: vote.voteId
              },
              header: { 'Access-Token': `Bearer ${token}` }
            });
            
            if (messageResponse.statusCode === 200 && messageResponse.data?.success && messageResponse.data?.messageId) {
              messageId = messageResponse.data.messageId;
              console.log('通过精准接口找到对应的 messageId:', messageId);
            }
          } catch (msgError) {
            console.error('通过精准接口查询 messageId 失败:', msgError);
          }
        }
        
        if (!vote || !messageId) {
          uni.showToast({ title: '未找到投票消息，请通过消息中心撤回', icon: 'none' });
          return;
        }
        
        const response = await uni.request({
          url: `${NETWORK_CONFIG.API_BASE_URL}/message/withdraw-vote`,
          method: 'POST',
          data: {
            messageId: messageId
          },
          header: {
            'Access-Token': `Bearer ${token}`,
            'Content-Type': 'application/json'
          }
        });
        
        // 解析响应数据
        let responseData;
        if (typeof response.data === 'string') {
          try {
            responseData = JSON.parse(response.data);
          } catch (e) {
            console.error('解析响应数据失败:', e);
            responseData = { success: false, message: '响应数据格式错误' };
          }
        } else {
          responseData = response.data;
        }
        
        console.log('撤回投票响应:', responseData);
        
        if (responseData && responseData.success) {
          uni.showToast({ 
            title: '投票已撤回', 
            icon: 'success' 
          });
          
          // 重新加载投票数据
          if (teamInfo.value?.teamId) {
            await loadTeamVotes(teamInfo.value.teamId);
          }
          
          // 重新获取团队信息
          await checkExistingTeam();
        } else {
          uni.showToast({ title: responseData?.message || '撤回失败', icon: 'none' });
        }
      } catch (error) {
        console.error('撤回投票失败:', error);
        uni.showToast({ title: '撤回失败，请重试', icon: 'none' });
      } finally {
        withdrawLoading.value = false;
      }
    };
    
    // 发起弹劾队长投票
    const initiateImpeachLeaderVote = async () => {
      if (!teamInfo.value || !teamInfo.value.teamId) {
        uni.showToast({ title: '团队信息不存在', icon: 'none' })
        return
      }
      
      // 显示输入原因的弹窗
      uni.showModal({
        title: '发起弹劾队长投票',
        content: '请输入弹劾原因',
        editable: true,
        placeholderText: '请输入弹劾原因...',
        success: async (res) => {
          if (res.confirm && res.content) {
            try {
              const token = uni.getStorageSync('accessToken')
              if (!token) {
                uni.showToast({ title: '请先登录', icon: 'none' })
                return
              }
              
              const currentUser = uni.getStorageSync('userInfo')
              let initiatorId = null
              if (currentUser && currentUser.uid) {
                initiatorId = currentUser.uid
              } else {
                try {
                  const tokenPayload = parseJwtToken(token)
                  initiatorId = tokenPayload.uid || tokenPayload.sub
                } catch (tokenError) {
                  console.error('解析token失败:', tokenError)
                  uni.showToast({ title: '用户信息获取失败，请重新登录', icon: 'none' })
                  return
                }
              }
              
              if (!initiatorId) {
                uni.showToast({ title: '用户信息获取失败，请重新登录', icon: 'none' })
                return
              }
              
              const response = await uni.request({
                url: `${NETWORK_CONFIG.API_BASE_URL}/team-vote/initiate-impeach-leader`,
                method: 'POST',
                data: {
                  teamId: teamInfo.value.teamId,
                  initiatorId: initiatorId,
                  reason: res.content
                },
                header: {
                  'Access-Token': `Bearer ${token}`,
                  'Content-Type': 'application/json'
                }
              })
              
              if (response.data && response.data.success) {
                uni.showToast({ title: '弹劾队长投票已发起', icon: 'success' })
                // 重新加载团队信息
                await checkExistingTeam()
              } else {
                uni.showToast({ title: response.data?.message || '发起投票失败', icon: 'none' })
              }
            } catch (error) {
              console.error('发起弹劾投票失败:', error)
              uni.showToast({ title: '操作失败，请重试', icon: 'none' })
            }
          }
        }
      })
    }
    
    // 转让队长
    const transferLeadership = async (newLeaderId) => {
      if (!teamInfo.value || !teamInfo.value.teamId) {
        uni.showToast({ title: '团队信息不存在', icon: 'none' })
        return
      }
      
      // 显示确认弹窗
      uni.showModal({
        title: '转让队长',
        content: '确定要将队长职位转让给该队员吗？转让后您将失去队长权限。',
        success: async (res) => {
          if (res.confirm) {
            try {
              const token = uni.getStorageSync('accessToken')
              if (!token) {
                uni.showToast({ title: '请先登录', icon: 'none' })
                return
              }
              
              const currentUser = uni.getStorageSync('userInfo')
              let currentLeaderId = null
              if (currentUser && currentUser.uid) {
                currentLeaderId = currentUser.uid
              } else {
                try {
                  const tokenPayload = parseJwtToken(token)
                  currentLeaderId = tokenPayload.uid || tokenPayload.sub
                } catch (tokenError) {
                  console.error('解析token失败:', tokenError)
                  uni.showToast({ title: '用户信息获取失败，请重新登录', icon: 'none' })
                  return
                }
              }
              
              if (!currentLeaderId) {
                uni.showToast({ title: '用户信息获取失败，请重新登录', icon: 'none' })
                return
              }
              
              const response = await uni.request({
                url: `${NETWORK_CONFIG.API_BASE_URL}/team/transfer-leadership`,
                method: 'POST',
                data: {
                  teamId: teamInfo.value.teamId,
                  currentLeaderId: currentLeaderId,
                  newLeaderId: newLeaderId
                },
                header: {
                  'Access-Token': `Bearer ${token}`,
                  'Content-Type': 'application/json'
                }
              })
              
              if (response.data && response.data.success) {
                uni.showToast({ title: '队长转让成功', icon: 'success' })
                // 重新加载团队信息
                await checkExistingTeam()
              } else {
                uni.showToast({ title: response.data?.message || '转让失败', icon: 'none' })
              }
            } catch (error) {
              console.error('转让队长失败:', error)
              uni.showToast({ title: '操作失败，请重试', icon: 'none' })
            }
          }
        }
      })
    }
    
    // 队员退出团队
    const leaveTeam = async () => {
      if (!teamInfo.value || !teamInfo.value.teamId) {
        uni.showToast({ title: '团队信息不存在', icon: 'none' })
        return
      }
      
      try {
        const token = uni.getStorageSync('accessToken')
        if (!token) {
          uni.showToast({ title: '请先登录', icon: 'none' })
          return
        }
        
        const currentUser = uni.getStorageSync('userInfo')
        let userId = null
        if (currentUser && currentUser.uid) {
          userId = currentUser.uid
        } else {
          try {
            const tokenPayload = parseJwtToken(token)
            userId = tokenPayload.uid || tokenPayload.sub
          } catch (tokenError) {
            console.error('解析token失败:', tokenError)
            uni.showToast({ title: '用户信息获取失败，请重新登录', icon: 'none' })
            return
          }
        }
        
        if (!userId) {
          uni.showToast({ title: '用户信息获取失败，请重新登录', icon: 'none' })
          return
        }
        
        console.log('退出团队，参数:', {
          teamId: teamInfo.value.teamId,
          userId: userId
        })
        
        const response = await uni.request({
          url: `${NETWORK_CONFIG.API_BASE_URL}/team/leave-team`,
          method: 'POST',
          data: {
            teamId: teamInfo.value.teamId,
            userId: userId
          },
          header: {
            'Access-Token': `Bearer ${token}`,
            'Content-Type': 'application/json'
          }
        })
        
        console.log('退出团队响应:', response)
        
        if (response.data && response.data.success) {
          uni.showToast({ title: '退出申请已提交，等待队长同意', icon: 'success' })
          
          // 退出申请已提交，重新加载团队信息和投票信息
          await checkExistingTeam()
          if (teamInfo.value?.teamId) {
            await loadTeamVotes(teamInfo.value.teamId)
          }
        } else {
          uni.showToast({ title: response.data?.message || '退出失败', icon: 'none' })
        }
      } catch (error) {
        console.error('退出团队失败:', error)
        uni.showToast({ title: '退出团队失败', icon: 'none' })
      }
    }
    
    // 队长解散团队
    const dissolveTeam = async () => {
      if (!teamInfo.value || !teamInfo.value.teamId) {
        uni.showToast({ title: '团队信息不存在', icon: 'none' })
        return
      }
      
      try {
        // 确认解散
        const confirmResult = await new Promise((resolve) => {
          uni.showModal({
            title: '解散团队',
            content: '确定要解散当前团队吗？解散后所有成员将收到通知。',
            confirmText: '确定解散',
            cancelText: '取消',
            success: (res) => resolve(res.confirm)
          })
        })
        
        if (!confirmResult) {
          return
        }
        
        const token = uni.getStorageSync('accessToken')
        if (!token) {
          uni.showToast({ title: '请先登录', icon: 'none' })
          return
        }
        
        const currentUser = uni.getStorageSync('userInfo')
        let leaderId = null
        if (currentUser && currentUser.uid) {
          leaderId = currentUser.uid
        } else {
          try {
            const tokenPayload = parseJwtToken(token)
            if (tokenPayload) {
              leaderId = tokenPayload.uid || tokenPayload.sub
            }
          } catch (tokenError) {
            console.error('解析token失败:', tokenError)
            uni.showToast({ title: '用户信息获取失败，请重新登录', icon: 'none' })
            return
          }
        }
        
        if (!leaderId) {
          uni.showToast({ title: '用户信息获取失败，请重新登录', icon: 'none' })
          return
        }
        
        console.log('解散团队，参数:', {
          teamId: teamInfo.value.teamId,
          leaderId: leaderId
        })
        
        const response = await uni.request({
          url: `${NETWORK_CONFIG.API_BASE_URL}/team/dissolve-team`,
          method: 'POST',
          data: {
            teamId: teamInfo.value.teamId,
            leaderId: leaderId
          },
          header: {
            'Access-Token': `Bearer ${token}`,
            'Content-Type': 'application/json'
          }
        })
        
        console.log('解散团队响应:', response)
        
        if (response.data && response.data.success) {
          uni.showToast({ title: '团队解散成功', icon: 'success' })
          
          // 解散团队后，更新团队状态为已解散，但保持团队信息
          if (teamInfo.value) {
            teamInfo.value.status = 2 // 设置为已解散状态
          }
          
          // 重新检查团队状态以获取最新的团队信息
          await checkExistingTeam()
        } else {
          uni.showToast({ title: response.data?.message || '解散失败', icon: 'none' })
        }
      } catch (error) {
        console.error('解散团队失败:', error)
        uni.showToast({ title: '解散团队失败', icon: 'none' })
      }
    }
    
    // 测试按钮点击
    const testRecreateClick = () => {
      console.log('🎯🎯🎯 按钮被点击了！');
      console.log('时间:', new Date().toLocaleTimeString());
      alert('按钮被点击了！');
      uni.showToast({ title: '按钮被点击了！', icon: 'success' });
    };

    // 重新创建团队（用于已解散的团队）
    const recreateTeamFromDissolved = async () => {
      console.log('🔥 重新创建团队按钮被点击！');
      console.log('当前团队信息:', teamInfo.value);
      console.log('团队状态:', teamInfo.value?.status);
      
      try {
        uni.showToast({ 
          title: '正在重新创建团队...', 
          icon: 'loading',
          duration: 2000
        });
        
        console.log('开始调用 createTeamImmediately...');
        await createTeamImmediately();
        
        console.log('✅ createTeamImmediately 调用完成');
        uni.showToast({ 
          title: '团队重新创建成功！', 
          icon: 'success',
          duration: 2000
        });
        
        // 重新检查团队状态
        await checkExistingTeam();
        
      } catch (error) {
        console.error('❌ 重新创建团队失败:', error);
        uni.showToast({ 
          title: '重新创建团队失败: ' + error.message, 
          icon: 'none',
          duration: 3000
        });
      }
    };
    
    const openTeamInvitationModal = async () => {
      try {
        // 先创建团队和队长的TeamMember记录
        const token = uni.getStorageSync('accessToken');
        const currentUser = uni.getStorageSync('userInfo');
        
        if (!token) {
          uni.showToast({ title: '请先登录', icon: 'none' });
          return;
        }
        
        let leaderId = null;
        if (currentUser && currentUser.uid) {
          leaderId = currentUser.uid;
        } else {
          try {
            const tokenPayload = parseJwtToken(token);
            if (tokenPayload) {
              leaderId = tokenPayload.uid || tokenPayload.sub;
            }
          } catch (tokenError) {
            console.error('解析token失败:', tokenError);
            uni.showToast({ title: '用户信息获取失败，请重新登录', icon: 'none' });
            return;
          }
        }
        
        if (!leaderId) {
          uni.showToast({ title: '用户信息获取失败，请重新登录', icon: 'none' });
          return;
        }
        
        console.log('开始创建团队，参数:', {
          taskId: taskData.value?.taskId,
          leaderId: leaderId,
          teamName: '临时团队'
        });
        
        // 创建团队和队长的TeamMember记录
        const response = await uni.request({
          url: `${NETWORK_CONFIG.API_BASE_URL}/team/create-invitation`,
          method: 'POST',
          data: {
            taskId: Number(taskData.value?.taskId),
            leaderId: Number(leaderId),
            teamName: '临时团队',
            inviteeIds: [] // 暂时不邀请任何人，只创建团队
          },
          header: {
            'Access-Token': `Bearer ${token}`,
            'Content-Type': 'application/json'
          }
        });
        
        console.log('团队创建响应:', response);
        
        if (response.data && response.data.success) {
          // 根据是否已存在显示不同消息
          if (response.data.isExisting) {
            uni.showToast({ title: '团队已存在', icon: 'success' });
          } else {
            uni.showToast({ title: '已为您创建团队', icon: 'success' });
          }
          
          // 保存团队信息到响应式数据
          if (response.data.teamInfo) {
            teamInfo.value = response.data.teamInfo;
            console.log('团队信息:', teamInfo.value);
          }
          
          // 打开邀请模态框
          showTeamInvitationModal.value = true;
        } else {
          uni.showToast({ title: response.data?.message || '团队创建失败', icon: 'none' });
        }
      } catch (error) {
        console.error('创建团队失败:', error);
        uni.showToast({ title: '创建团队失败', icon: 'none' });
      }
    };
    
    const closeTeamInvitationModal = () => {
      showTeamInvitationModal.value = false;
    };
    
    const handleTeamInvitationConfirm = async (teamId) => {
      console.log('团队邀请创建成功，团队ID:', teamId);
      // 完全刷新团队信息（会自动清除并重新初始化 invitedUsers）
      await checkExistingTeam();
      // 重新加载投票信息
      if (teamInfo.value?.teamId) {
        await loadTeamVotes(teamInfo.value.teamId);
      }
    };
    
    const handleUpdateTeamName = (newTeamName) => {
      if (teamInfo.value) {
        teamInfo.value.teamName = newTeamName;
      }
    };
    
    const loadTeamInfo = async (teamId = null) => {
      try {
        const token = uni.getStorageSync('accessToken');
        const taskIdVal = taskData.value?.taskId || task.value?.taskId;
        
        if (!taskIdVal) return;
        
        // 构建查询参数
        let url = `${NETWORK_CONFIG.API_BASE_URL}/team/info?taskId=${taskIdVal}`;
        if (teamId) {
          url += `&teamId=${teamId}`;
        }
        
        const response = await uni.request({
          url: url,
          method: 'GET',
          header: { 'Access-Token': `Bearer ${token}` }
        });
        
        if (response.data && response.data.success) {
          teamInfo.value = response.data.data;
          console.log('loadTeamInfo - 团队信息加载成功:', teamInfo.value);
          console.log('loadTeamInfo - teamInfo.value.leaderId:', teamInfo.value.leaderId);
          console.log('loadTeamInfo - currentUserId:', currentUserId.value);
          
          // 判断用户是否是队长
          if (teamInfo.value) {
            const currentUser = uni.getStorageSync('userInfo');
            let currentUid = null;
            if (currentUser && currentUser.uid) {
              currentUid = currentUser.uid;
            } else {
              try {
                const tokenPayload = parseJwtToken(token);
                if (tokenPayload) {
                  currentUid = tokenPayload.uid || tokenPayload.sub;
                }
              } catch (tokenError) {
                console.error('解析token失败:', tokenError);
              }
            }
            
            if (currentUid) {
              isTeamLeader.value = teamInfo.value.leaderId == currentUid;
              console.log('设置isTeamLeader:', isTeamLeader.value, 'leaderId:', teamInfo.value.leaderId, 'currentUid:', currentUid);
            }
          }
          
          // 加载团队信息后，获取投票数据
          if (teamInfo.value?.teamId) {
            await loadTeamVotes(teamInfo.value.teamId);
            await loadVoteHistory(teamInfo.value.teamId);
          }
        } else {
          console.log('团队信息API返回失败，可能是个人挑战或API未实现:', response.data);
          // 如果是个人挑战，不显示团队信息是正常的
          teamInfo.value = null;
          isTeamLeader.value = false;
        }
      } catch (error) {
        console.error('加载团队信息失败:', error);
        // API失败时不影响页面显示，只是不显示团队信息
        teamInfo.value = null;
        isTeamLeader.value = false;
      }
    };
    
    // 加载进行中的投票
    const loadTeamVotes = async (teamId) => {
      try {
        const token = uni.getStorageSync('accessToken');
        if (!token) {
          console.warn('loadTeamVotes: 未找到 token');
          return;
        }
        
        console.log('loadTeamVotes: 开始加载投票，teamId:', teamId);
        
        const response = await uni.request({
          url: `${NETWORK_CONFIG.API_BASE_URL}/team-vote/active-votes?teamId=${teamId}`,
          method: 'GET',
          header: { 'Access-Token': `Bearer ${token}` }
        });
        
        console.log('loadTeamVotes: 响应状态码:', response.statusCode);
        console.log('loadTeamVotes: 响应数据:', response.data);
        
        if (response.data && response.data.success) {
          activeTeamVotes.value = response.data.data || [];
          console.log('加载进行中的投票成功，数量:', activeTeamVotes.value.length);
          // 打印每个投票的详细信息，特别是 messageId
          activeTeamVotes.value.forEach((vote, index) => {
            console.log(`投票 ${index + 1}:`, {
              voteId: vote.voteId,
              id: vote.id,
              messageId: vote.messageId,
              voteType: vote.voteType,
              hasVoted: vote.hasVoted
            });
          });
        } else {
          console.warn('loadTeamVotes: 响应未成功，data:', response.data);
        }
      } catch (error) {
        console.error('加载进行中的投票失败:', error);
      }
    };
    
    // 加载投票记录（历史）
    const loadVoteHistory = async (teamId) => {
      try {
        const token = uni.getStorageSync('accessToken');
        if (!token) return;
        
        const response = await uni.request({
          url: `${NETWORK_CONFIG.API_BASE_URL}/team-vote/history?teamId=${teamId}`,
          method: 'GET',
          header: { 'Access-Token': `Bearer ${token}` }
        });
        
        if (response.data && response.data.success) {
          voteHistory.value = response.data.data || [];
          console.log('加载投票记录成功:', voteHistory.value);
        }
      } catch (error) {
        console.error('加载投票记录失败:', error);
      }
    };
    
    // 更新团队名称
    const updateTeamName = async (teamId, newTeamName) => {
      try {
        const token = uni.getStorageSync('accessToken');
        if (!token) {
          uni.showToast({ title: '请先登录', icon: 'none' });
          return;
        }
        
        const response = await uni.request({
          url: `${NETWORK_CONFIG.API_BASE_URL}/team/update-name`,
          method: 'POST',
          data: {
            teamId: teamId,
            teamName: newTeamName
          },
          header: {
            'Access-Token': `Bearer ${token}`,
            'Content-Type': 'application/json'
          }
        });
        
        if (response.data && response.data.success) {
          uni.showToast({ title: '团队名称更新成功', icon: 'success' });
          // 更新本地团队信息
          if (teamInfo.value) {
            teamInfo.value.teamName = newTeamName;
          }
        } else {
          uni.showToast({ title: response.data?.message || '更新失败', icon: 'none' });
        }
      } catch (error) {
        console.error('更新团队名称失败:', error);
        uni.showToast({ title: '更新团队名称失败', icon: 'none' });
      }
    };
    
    // 处理驳回申请完成
    const handleRejectCompletion = () => {
      console.log('点击驳回申请按钮');
      uni.showModal({
        title: '驳回申请',
        content: '确定要驳回这个完成申请吗？',
        success: async (res) => {
          if (res.confirm) {
            console.log('用户确认驳回申请');
            console.log('completePreview.value:', completePreview.value);
            console.log('messageId:', completePreview.value?.messageId);
            console.log('proof:', completePreview.value?.proof);
            try {
              const token = uni.getStorageSync('accessToken');
              const requestData = `approve=false&proof=${encodeURIComponent(completePreview.value?.proof || '')}&id=${completePreview.value?.messageId}`;
              console.log('请求数据:', requestData);
              const response = await uni.request({
                url: `${NETWORK_CONFIG.API_BASE_URL}/message/handle-task-completion`,
                method: 'POST',
                header: { 
                  'Access-Token': `Bearer ${token}`,
                  'Content-Type': 'application/x-www-form-urlencoded'
                },
                data: requestData
              });
              
              console.log('驳回申请响应:', response);
              
              if (response.statusCode === 200) {
                uni.showToast({ title: '已驳回申请', icon: 'success' });
                closeCompletePreview();
                // 刷新任务数据
                await fetchTaskDetail(taskId);
              } else {
                uni.showToast({ title: '驳回失败', icon: 'error' });
              }
            } catch (error) {
              console.error('驳回申请失败:', error);
              uni.showToast({ title: '驳回失败', icon: 'error' });
            }
          }
        }
      });
    };
    
    // 处理同意申请完成
    const handleApproveCompletion = () => {
      console.log('点击同意申请按钮');
      uni.showModal({
        title: '同意申请',
        content: '确定要同意这个完成申请吗？',
        success: async (res) => {
          if (res.confirm) {
            console.log('用户确认同意申请');
            console.log('completePreview.value:', completePreview.value);
            console.log('messageId:', completePreview.value?.messageId);
            console.log('proof:', completePreview.value?.proof);
            try {
              // 从 userStore 获取 token
              const token = userStore.token;
              if (!token) {
                uni.showToast({ title: '请先登录', icon: 'none' });
                return;
              }
              
              const requestData = `approve=true&proof=${encodeURIComponent(completePreview.value?.proof || '')}&id=${completePreview.value?.messageId}`;
              console.log('请求数据:', requestData);
              
              let response = await uni.request({
                url: `${NETWORK_CONFIG.API_BASE_URL}/message/handle-task-completion`,
                method: 'POST',
                header: { 
                  'Access-Token': `Bearer ${token}`,
                  'Content-Type': 'application/x-www-form-urlencoded'
                },
                data: requestData
              });
              
              // 如果返回401，提示用户重新登录
              if (response.statusCode === 401) {
                console.log('收到401响应，token已过期');
                uni.showToast({ title: '登录已过期，请重新登录', icon: 'none' });
                // 清除用户状态并跳转到登录页面
                userStore.clearUserState();
                uni.reLaunch({
                  url: '/pages/auth/login/index'
                });
                return;
              }
              
              console.log('同意申请响应:', response);
              
              if (response.statusCode === 200) {
                uni.showToast({ title: '已同意申请', icon: 'success' });
                closeCompletePreview();
                // 刷新任务数据
                await fetchTaskDetail(taskId);
              } else {
                uni.showToast({ title: '同意失败', icon: 'error' });
              }
            } catch (error) {
              console.error('同意申请失败:', error);
              uni.showToast({ title: '同意失败', icon: 'error' });
            }
          }
        }
      });
    };
    const applyCompleteTask = async () => {
      if (!completeProof.value) {
        uni.showToast({ title: '请填写完成证明', icon: 'none' });
        return;
      }
      uni.showLoading({ title: '提交申请中...' });
      
      // 验证每个铭牌的贡献比例总和是否为100%
      let isValid = true;
      taskData.value?.badges.forEach(badge => {
        if (calculateTotalPercentage(badge.id) !== 100) {
          isValid = false;
        }
      });
      if (!isValid) {
        uni.hideLoading();
        uni.showToast({ title: '每个铭牌的贡献比例总和必须为100%', icon: 'none' });
        return;
      }
      
      // 如果是团队任务，验证所有团队成员都在铭牌分配中，且每个成员在每个铭牌中至少有1%
      if (isTeamTask() && teamInfo.value && teamInfo.value.members) {
        const teamMembers = teamInfo.value.members;
        const teamMemberIds = new Set(teamMembers.map(m => String(m.userId)));
        
        // 验证每个铭牌
        for (const badge of taskData.value?.badges || []) {
          if (!badgeContributors[badge.id] || badgeContributors[badge.id].length === 0) {
            uni.hideLoading();
            uni.showToast({ 
              title: `铭牌 ${getBadgeNameByAssociation(badge.association)} Lv${badge.level} 必须分配贡献者`,
              icon: 'none',
              duration: 3000
            });
            return;
          }
          
          // 检查每个团队成员是否在该铭牌中至少有1%的分配
          for (const member of teamMembers) {
            const memberId = String(member.userId);
            const contributor = badgeContributors[badge.id].find(c => String(c.uid) === memberId);
            
            if (!contributor) {
              uni.hideLoading();
              uni.showToast({ 
                title: `成员 ${getUserNickname(member.userId)} 未分配到铭牌 ${getBadgeNameByAssociation(badge.association)} Lv${badge.level}`,
                icon: 'none',
                duration: 3000
              });
              return;
            }
            
            // 检查是否是团队成员
            if (!teamMemberIds.has(String(contributor.uid))) {
              uni.hideLoading();
              uni.showToast({ 
                title: `只能分配给团队成员，用户 ${contributor.uid} 不是团队成员`,
                icon: 'none',
                duration: 3000
              });
              return;
            }
            
            // 检查是否至少有1%的分配
            if (contributor.percentage < 1) {
              uni.hideLoading();
              uni.showToast({ 
                title: `成员 ${getUserNickname(member.userId)} 在铭牌 ${getBadgeNameByAssociation(badge.association)} Lv${badge.level} 中的分配比例必须至少为1%`,
                icon: 'none',
                duration: 3000
              });
              return;
            }
          }
          
          // 检查是否有非团队成员被分配
          for (const contributor of badgeContributors[badge.id]) {
            if (!teamMemberIds.has(String(contributor.uid))) {
              uni.hideLoading();
              uni.showToast({ 
                title: `只能分配给团队成员，用户 ${contributor.uid} 不是团队成员`,
                icon: 'none',
                duration: 3000
              });
              return;
            }
          }
        }
      }
      const badges = taskData.value?.badges.map(badge => ({
        badgeId: badge.id,
        contributors: badgeContributors[badge.id]
      }));
      try {
        const token = uni.getStorageSync('accessToken');
        if (!token) {
          uni.showToast({ title: '请先登录', icon: 'none' });
          return;
        }
        
        const requestUrl = `${NETWORK_CONFIG.API_BASE_URL}/task/applycomplete?taskId=${taskData.value?.taskId}&proof=${encodeURIComponent(completeProof.value)}`;
        const requestData = { badges: badges };
        
        console.log('申请完成任务请求参数:', {
          url: requestUrl,
          taskId: taskData.value?.taskId,
          proof: completeProof.value,
          badges: badges,
          requestData: requestData
        });
        
        const response = await uni.request({
          url: requestUrl,
          method: 'POST',
          data: requestData,
          header: {
            'Content-Type': 'application/json',
            'Access-Token': `Bearer ${token}`
          }
        });
        if (response.statusCode === 200) {
          uni.hideLoading();
          uni.showToast({ title: '申请完成任务成功！', icon: 'success' });
          // 标记为已申请，并刷新待处理状态
          hasAppliedCompletion.value = true;
          await checkPendingMessages();
        } else {
          throw new Error(response.data?.message || '申请失败');
        }
      } catch (e) {
        uni.hideLoading();
        uni.showToast({ title: e.message || '申请失败', icon: 'none' });
      }
    };
    const cancelCompletionByTask = async () => {
      uni.showModal({
        title: '撤回完成申请',
        content: '确认撤回已提交的完成申请吗？',
        success: async (res) => {
          if (!res.confirm) return;
          try {
            const token = uni.getStorageSync('accessToken');
            if (!token) throw new Error('请先登录');
            const taskIdVal = taskData.value?.taskId || task.value?.taskId;
            if (!taskIdVal) throw new Error('任务 ID 缺失');
            const response = await uni.request({
              url: `${NETWORK_CONFIG.API_BASE_URL}/message/cancel-task-completion-by-task?taskId=${taskIdVal}`,
              method: 'POST',
              header: { 'Access-Token': `Bearer ${token}` }
            });
            if (response.statusCode === 200) {
              uni.showToast({ title: '已撤回完成申请', icon: 'success' });
              hasAppliedCompletion.value = false;
              await checkPendingMessages();
            } else if (response.statusCode === 404) {
              // 回退：查找消息ID并按ID撤回
              const respId = await uni.request({
                url: `${NETWORK_CONFIG.API_BASE_URL}/message/completion-apply/message-id?taskId=${taskIdVal}`,
                method: 'GET',
                header: { 'Access-Token': `Bearer ${token}` }
              });
              if (respId.statusCode === 200 && respId.data && respId.data.messageId) {
                const msgId = respId.data.messageId;
                const respCancel = await uni.request({
                  url: `${NETWORK_CONFIG.API_BASE_URL}/message/cancel-task-completion?id=${msgId}`,
                  method: 'POST',
                  header: { 'Access-Token': `Bearer ${token}` }
                });
                if (respCancel.statusCode === 200) {
                  uni.showToast({ title: '已撤回完成申请', icon: 'success' });
                  hasAppliedCompletion.value = false;
                  await checkPendingMessages();
                } else {
                  throw new Error(respCancel.data?.message || '撤回失败');
                }
              } else {
                throw new Error(respId.data?.message || '未找到申请消息');
              }
            } else {
              throw new Error(response.data?.message || '撤回失败');
            }
          } catch (e) {
            uni.showToast({ title: e.message || '撤回失败', icon: 'none' });
          }
        }
      });
    };
    const handleError = (err, context) => {
      uni.showToast({ title: '操作失败，请稍后重试', icon: 'none', duration: 2000 });
    };
    uni.onError((err) => { handleError(err, '全局'); });
    const debounce = (func, wait) => {
      let timeout;
      return function executedFunction(...args) {
        const later = () => {
          clearTimeout(timeout);
          func(...args);
        };
        clearTimeout(timeout);
        timeout = setTimeout(later, wait);
      };
    };
    const debouncedValidateTotalPercentage = debounce(validateTotalPercentage, 300);
    const allBadgesValid = computed(() => {
      if (!taskData.value?.badges) return false;
      return taskData.value.badges.every(b => calculateTotalPercentage(b.id) === 100);
    });
    const canSubmitComplete = computed(() => {
      return !!completeProof.value && allBadgesValid.value;
    });
    const goToApplyComplete = () => {
      scrollIntoView.value = 'apply-complete-anchor';
      // 小程序场景下，再触发一次以确保滚动
      setTimeout(() => { scrollIntoView.value = ''; }, 300);
    };
    // 数字格式化函数 - 使用千分位分隔符，始终显示完整数字
    const formatNumber = (num) => {
      if (num === null || num === undefined || isNaN(num)) {
        return '0';
      }
      const number = Number(num);
      return number.toLocaleString();
    };
    // 百分比格式化函数
    const formatPercentage = (num) => {
      if (num === null || num === undefined || isNaN(num)) {
        return '0';
      }
      return Number(num).toLocaleString();
    };
    // 字符数格式化函数 - 不使用中文单位
    const formatCharacterCount = (num) => {
      if (num === null || num === undefined || isNaN(num)) {
        return '0';
      }
      return Number(num).toLocaleString();
    };
    // 日期时间格式化函数
    const formatDateTime = (timestamp) => {
      if (!timestamp) return '未知时间';
      const date = new Date(timestamp);
      const year = date.getFullYear();
      const month = String(date.getMonth() + 1).padStart(2, '0');
      const day = String(date.getDate()).padStart(2, '0');
      const hours = String(date.getHours()).padStart(2, '0');
      const minutes = String(date.getMinutes()).padStart(2, '0');
      return `${year}-${month}-${day} ${hours}:${minutes}`;
    };

    // 工作记录相关状态和方法
    const workTimes = ref([]);
    const workLoading = ref(false);
    const workError = ref(null);
    const showWorkControls = computed(() => {
      if (taskData.value?.status !== '2') return false; // 只在进行中时显示工作控制
      
      const currentUserId = userStore.profile?.uid;
      if (!currentUserId) return false;
      
      // 发布者不能看到工作控制按钮
      const publisherId = taskData.value?.publisherId;
      const isPublisher = publisherId && String(publisherId) === String(currentUserId);
      if (isPublisher) {
        console.log('showWorkControls: 发布者不能看到工作控制按钮');
        return false;
      }
      
      // 现在所有任务都是团队任务，检查用户是否是团队成员
      const isChallenger = teamInfo.value && teamInfo.value.members && 
        teamInfo.value.members.some(member => String(member.userId) === String(currentUserId));
      
      console.log('showWorkControls 调试信息:', {
        currentUserId,
        publisherId,
        isPublisher,
        isChallenger,
        status: taskData.value?.status,
        result: isChallenger
      });
      
      return isChallenger;
    });
    const hasOngoingWork = computed(() => {
      if (!Array.isArray(workTimes.value)) return false;
      return workTimes.value.some(wt => {
        const endVal = wt?.endTime ?? wt?.end_at ?? wt?.end;
        return endVal === null || endVal === undefined;
      });
    });
    const startWorking = ref(false);
    const endWorking = ref(false);

    const normalizeArrayResponse = (resData) => {
      if (Array.isArray(resData)) return resData;
      if (resData && Array.isArray(resData.data)) return resData.data;
      if (resData && Array.isArray(resData.result)) return resData.result;
      if (resData && Array.isArray(resData.payload)) return resData.payload;
      return [];
    };

    const fetchWorkTimes = async () => {
      workLoading.value = true;
      workError.value = null;
      try {
        const token = uni.getStorageSync('accessToken');
        if (!token) throw new Error('请先登录');
        const taskIdVal = taskData.value?.taskId || task.value?.taskId || taskId;
        // 若仍然拿不到ID，安静退出，不提示错误（等详情加载完后再拉取）
        if (!taskIdVal) { return; }
        const response = await uni.request({
          url: `${NETWORK_CONFIG.API_BASE_URL}/work/times?taskId=${taskIdVal}`,
          method: 'GET',
          header: { 'Access-Token': `Bearer ${token}` },
          timeout: 8000
        });
        if (response.statusCode === 200 && response.data !== undefined) {
          workTimes.value = normalizeArrayResponse(response.data);
        } else {
          throw new Error(response.data?.message || '加载工作记录失败');
        }
      } catch (e) {
        // 仅在有明确错误时提示；任务ID缺失等初始化过程不提示
        if (e && e.message && !/任务 ID 缺失/.test(e.message)) {
          workError.value = e.message;
        }
      } finally {
        workLoading.value = false;
      }
    };

    const startWork = async () => {
      if (startWorking.value) return;
      startWorking.value = true;
      uni.showLoading({ title: '开始中...' });
      try {
        const token = uni.getStorageSync('accessToken');
        if (!token) throw new Error('请先登录');
        const taskIdVal = taskData.value?.taskId || task.value?.taskId;
        if (!taskIdVal) throw new Error('任务 ID 缺失');
        const response = await uni.request({
          url: `${NETWORK_CONFIG.API_BASE_URL}/work/start?taskId=${taskIdVal}`,
          method: 'POST',
          header: { 'Access-Token': `Bearer ${token}` },
          timeout: 8000
        });
        if (response.statusCode === 200 && response.data) {
          uni.hideLoading();
          uni.showToast({ title: '开始工作成功！', icon: 'success' });
          await fetchWorkTimes(); // 刷新工作记录
        } else {
          throw new Error(response.data?.message || '开始工作失败');
        }
      } catch (e) {
        uni.hideLoading();
        uni.showToast({ title: e.message || '开始工作失败', icon: 'none' });
      } finally {
        startWorking.value = false;
      }
    };

    const endWork = async () => {
      if (endWorking.value) return;
      endWorking.value = true;
      uni.showLoading({ title: '结束中...' });
      try {
        const token = uni.getStorageSync('accessToken');
        if (!token) throw new Error('请先登录');
        const taskIdVal = taskData.value?.taskId || task.value?.taskId;
        if (!taskIdVal) throw new Error('任务 ID 缺失');
        const response = await uni.request({
          url: `${NETWORK_CONFIG.API_BASE_URL}/work/end?taskId=${taskIdVal}`,
          method: 'POST',
          header: { 'Access-Token': `Bearer ${token}` },
          timeout: 8000
        });
        if (response.statusCode === 200 && response.data) {
          uni.hideLoading();
          uni.showToast({ title: '结束工作成功！', icon: 'success' });
          await fetchWorkTimes(); // 刷新工作记录
        } else {
          throw new Error(response.data?.message || '结束工作失败');
        }
      } catch (e) {
        uni.hideLoading();
        uni.showToast({ title: e.message || '结束工作失败', icon: 'none' });
      } finally {
        endWorking.value = false;
      }
    };

    // 任务取消相关方法
    const cancelTaskApply = async () => {
      uni.showModal({
        title: '确认撤回申请',
        content: '确定要撤回对任务《' + taskData.value?.title + '》的申请吗？',
        success: async (res) => {
          if (res.confirm) {
            uni.showLoading({ title: '撤回申请中...' });
            try {
              const token = uni.getStorageSync('accessToken');
              if (!token) throw new Error('请先登录');
              const taskIdVal = taskData.value?.taskId || task.value?.taskId;
              if (!taskIdVal) throw new Error('任务 ID 缺失');
              
              const response = await uni.request({
                url: `${NETWORK_CONFIG.API_BASE_URL}/task/cancel-apply?taskId=${taskIdVal}`,
                method: 'POST',
                header: { 'Access-Token': `Bearer ${token}` },
                timeout: 8000
              });
              
              if (response.statusCode === 200) {
                uni.hideLoading();
                uni.showToast({ title: '申请已撤回', icon: 'success' });
                await fetchTaskDetail(taskIdVal); // 刷新任务详情
                await checkUserApplied(); // 重新检查用户申请状态
              } else {
                throw new Error(response.data?.message || '撤回申请失败');
              }
            } catch (e) {
              uni.hideLoading();
              uni.showToast({ title: e.message || '撤回申请失败', icon: 'none' });
            }
          }
        }
      });
    };

    const openCancelRequestModal = () => {
      cancelReason.value = '';
      showCancelRequestModal.value = true;
    };

    const closeCancelRequestModal = () => {
      showCancelRequestModal.value = false;
      cancelReason.value = '';
    };

    const submitCancelRequest = async () => {
      if (!cancelReason.value.trim()) {
        uni.showToast({ title: '请输入取消原因', icon: 'none' });
        return;
      }
      
      uni.showLoading({ title: '提交申请中...' });
      try {
        const token = uni.getStorageSync('accessToken');
        if (!token) throw new Error('请先登录');
        const taskIdVal = taskData.value?.taskId || task.value?.taskId;
        if (!taskIdVal) throw new Error('任务 ID 缺失');
        
        const response = await uni.request({
          url: `${NETWORK_CONFIG.API_BASE_URL}/task/request-cancel?taskId=${taskIdVal}&reason=${encodeURIComponent(cancelReason.value)}`,
          method: 'POST',
          header: { 'Access-Token': `Bearer ${token}` },
          timeout: 8000
        });
        
        if (response.statusCode === 200) {
          uni.hideLoading();
          uni.showToast({ title: '取消申请已发送', icon: 'success' });
          closeCancelRequestModal();
          await fetchTaskDetail(taskIdVal); // 刷新任务详情
        } else {
          throw new Error(response.data?.message || '提交申请失败');
        }
      } catch (e) {
        uni.hideLoading();
        uni.showToast({ title: e.message || '提交申请失败', icon: 'none' });
      }
    };

    const deleteTask = async () => {
      uni.showModal({
        title: '确认删除任务',
        content: '确定要删除任务《' + taskData.value?.title + '》吗？删除后无法恢复。',
        success: async (res) => {
          if (res.confirm) {
            uni.showLoading({ title: '删除中...' });
            try {
              const token = uni.getStorageSync('accessToken');
              if (!token) throw new Error('请先登录');
              const taskIdVal = taskData.value?.taskId || task.value?.taskId;
              if (!taskIdVal) throw new Error('任务 ID 缺失');
              
              const response = await uni.request({
                url: `${NETWORK_CONFIG.API_BASE_URL}/task/delete?taskId=${taskIdVal}`,
                method: 'DELETE',
                header: { 'Access-Token': `Bearer ${token}` },
                timeout: 8000
              });
              
              if (response.statusCode === 200) {
                uni.hideLoading();
                uni.showToast({ title: '任务已删除', icon: 'success' });
                // 返回上一页
                setTimeout(() => {
                  uni.navigateBack();
                }, 1500);
              } else {
                throw new Error(response.data?.message || '删除任务失败');
              }
            } catch (e) {
              uni.hideLoading();
              uni.showToast({ title: e.message || '删除任务失败', icon: 'none' });
            }
          }
        }
      });
    };

    // 跳转到消息中心
    const goToMessages = () => {
      uni.navigateTo({
        url: '/pages/message/index'
      });
    };

    // 处理任务取消申请被同意的事件
    const handleTaskCancelApproved = async (eventData) => {
      console.log('收到任务取消申请被同意的事件:', eventData);
      if (eventData.taskId && String(eventData.taskId) === String(taskId)) {
        console.log('当前任务被取消，刷新任务详情');
        // 刷新任务详情
        await fetchTaskDetail(taskId);
        // 重新检查用户申请状态
        await checkUserApplied();
        // 重新检查待处理消息
        await checkPendingMessages();
        uni.showToast({ 
          title: '任务已取消，状态已更新', 
          icon: 'success' 
        });
      }
    };

    // 处理团队成员变更消息
    const handleTeamMemberChange = async (message) => {
      console.log('收到团队成员变更消息:', message);
      
      // 检查是否与当前任务相关
      if (message.taskId && String(message.taskId) === String(taskId)) {
        console.log('当前任务的团队成员发生变更，刷新团队信息');
        
        // 重新获取团队信息
        await checkExistingTeam();
        
        // 显示通知
        if (message.action === 'join') {
          uni.showToast({ 
            title: '有新成员加入团队', 
            icon: 'success',
            duration: 2000
          });
        } else if (message.action === 'leave') {
          uni.showToast({ 
            title: '有成员离开团队', 
            icon: 'none',
            duration: 2000
          });
        } else if (message.action === 'remove') {
          uni.showToast({ 
            title: '有成员被移除', 
            icon: 'none',
            duration: 2000
          });
        }
      }
    };

    // 处理团队邀请消息
    const handleTeamInvitationMessage = async (message) => {
      console.log('收到团队邀请消息:', message);
      
      // 检查是否与当前任务相关
      if (message.taskId && String(message.taskId) === String(taskId)) {
        console.log('当前任务收到新的团队邀请');
        
        // 重新获取团队信息以更新待处理邀请
        await checkExistingTeam();
        
        uni.showToast({ 
          title: '收到新的团队邀请', 
          icon: 'success',
          duration: 2000
        });
      }
    };

    // 处理团队成员加入消息
    const handleTeamMemberJoined = async (message) => {
      console.log('收到团队成员加入消息:', message);
      
      // 检查是否与当前任务相关
      if (message.taskId && String(message.taskId) === String(taskId)) {
        console.log('当前任务有新成员加入，刷新团队信息');
        
        // 重新获取团队信息
        await checkExistingTeam();
        
        // 显示通知
        uni.showToast({ 
          title: `${message.newMemberName || '新成员'} 加入了团队`, 
          icon: 'success',
          duration: 2000
        });
      }
    };

    // 处理团队成员退出消息
    const handleTeamMemberLeft = async (message) => {
      console.log('收到团队成员退出消息:', message);
      
      // 检查是否与当前任务相关
      if (message.taskId && String(message.taskId) === String(taskId)) {
        console.log('当前任务有成员退出，刷新团队信息');
        
        // 重新获取团队信息
        await checkExistingTeam();
        
        // 显示通知
        uni.showToast({ 
          title: `${message.leftMemberName || '成员'} 退出了团队`, 
          icon: 'none',
          duration: 2000
        });
      }
    };

    // 处理团队成员被移除消息
    const handleTeamMemberRemoved = async (message) => {
      console.log('收到团队成员被移除消息:', message);
      
      // 检查是否与当前任务相关
      if (message.taskId && String(message.taskId) === String(taskId)) {
        console.log('当前任务有成员被移除，刷新团队信息');
        
        // 重新获取团队信息
        await checkExistingTeam();
        
        // 显示通知
        uni.showToast({ 
          title: `${message.removedMemberName || '成员'} 被移除了`, 
          icon: 'none',
          duration: 2000
        });
      }
    };

    // 处理团队投票发起消息
    const handleTeamVoteInitiated = async (message) => {
      console.log('收到团队投票发起消息:', message);
      
      // 检查是否与当前任务相关
      if (message.taskId && String(message.taskId) === String(taskId)) {
        console.log('当前任务有新的投票发起，刷新团队信息');
        
        // 重新获取团队信息
        await checkExistingTeam();
        
        // 显示通知
        uni.showToast({ 
          title: `有新的${message.voteTitle || '投票'}发起`, 
          icon: 'none',
          duration: 2000
        });
      }
    };

    // 处理团队投票结果消息
    const handleTeamVoteResult = async (message) => {
      console.log('收到团队投票结果消息:', message);
      
      // 检查是否与当前任务相关
      if (message.taskId && String(message.taskId) === String(taskId)) {
        console.log('当前任务投票结果已出，刷新团队信息');
        
        // 重新获取团队信息
        await checkExistingTeam();
        
        // 显示通知
        let resultText = '';
        if (message.resultType === 'member_removed') {
          resultText = '投票通过，成员已被移除';
        } else if (message.resultType === 'leader_impeached') {
          resultText = '投票通过，队长已被弹劾';
        } else {
          resultText = '投票结果已出';
        }
        
        uni.showToast({ 
          title: resultText, 
          icon: 'none',
          duration: 2000
        });
      }
    };

    onLoad(async (options) => {
      uni.setNavigationBarTitle({ title: '任务详情' });
      taskId = options.id || options.taskId || options.task_id;
      const messageId = options.messageId;
      const showCompletion = options.showCompletion === 'true';
      console.log('页面加载参数:', { options, taskId, messageId, showCompletion });
      
      // 确保用户信息已初始化
      if (!userStore.isInitialized) {
        console.log('用户信息未初始化，开始初始化...');
        await userStore.initialize();
      }
      
      console.log('当前用户信息:', { 
        userStore: userStore, 
        profile: userStore.profile,
        uid: userStore.profile?.uid,
        currentUserId: currentUserId.value,
        isInitialized: userStore.isInitialized
      });
      
      if (taskId) {
        await fetchTaskDetail(taskId);
        await fetchWorkTimes(); // 详情完成后再拉取工作记录，避免任务ID为空
        await checkPendingMessages(); // 检查待处理消息
        await checkUserApplied(); // 检查用户申请状态
        await checkExistingTeam(); // 检查是否已有团队，决定是否默认勾选组队模式
        
        // 如果是从消息跳转过来且需要显示申请完成详情
        if (showCompletion && messageId) {
          console.log('从消息跳转过来，显示申请完成详情，消息ID:', messageId);
          // 延迟一点时间确保任务数据已加载完成
          setTimeout(async () => {
            await fetchApplyCompletePreview();
            showCompletePreview.value = true;
          }, 500);
        }
      } else {
        error.value = "任务 ID 缺失";
        loading.value = false;
      }
      
      // 监听任务取消申请被同意的事件
      uni.$on('task-cancel-approved', handleTaskCancelApproved);
      
      // 监听WebSocket消息
      uni.$on('team-member-change', handleTeamMemberChange);
      uni.$on('team-invitation', handleTeamInvitationMessage);
      uni.$on('team-member-joined', handleTeamMemberJoined);
      uni.$on('team-member-left', handleTeamMemberLeft);
      uni.$on('team-member-removed', handleTeamMemberRemoved);
      uni.$on('team-vote-initiated', handleTeamVoteInitiated);
      uni.$on('team-vote-result', handleTeamVoteResult);
    });
    onShow(() => {});
    onHide(() => {});
    onUnload(() => {
      // 清理事件监听器
      uni.$off('task-cancel-approved', handleTaskCancelApproved);
      uni.$off('team-member-change', handleTeamMemberChange);
      uni.$off('team-invitation', handleTeamInvitationMessage);
    });
    return {
      task,
      loading,
      error,
      scrollIntoView,
      defaultAvatar,
      getStatusText,
      getBadgeNameByAssociation,
      moveToTaskLocation,
      applyForTask,
      challengeContent,
      showApplyCompleteBtn,
      completeProof,
      canSubmitComplete,
      goToApplyComplete,
      showCompletePreview,
      previewLoading,
      previewError,
      completePreview,
      viewApplyCompleteInfo,
      closeCompletePreview,
      badgeContributions,
      applyCompleteTask,
      currentUserId,
      isPublisherAndInProgress,
      badgeContributors,
      addContributor,
      removeContributor,
      selectContributor,
      clearContributor,
      getTeamMembersForBadge,
      calculateTotalPercentage,
      validateTotalPercentage,
      debouncedValidateTotalPercentage,
      userStore,
      mapMarkers,
      refreshing,
      onRefresh,
      handleError,
      taskData,
      currentUserId,
      formatNumber,
      formatPercentage,
      formatCharacterCount,
      workTimes,
      workLoading,
      workError,
      showWorkControls,
      hasOngoingWork,
      startWorking,
      endWorking,
      startWork,
      endWork,
      formatDateTime,
      // 任务取消相关
      showTaskActions,
      canCancelApply,
      canRequestCancel,
      canDeleteTask,
      showCancelRequestModal,
      cancelReason,
      cancelTaskApply,
      openCancelRequestModal,
      closeCancelRequestModal,
      submitCancelRequest,
      hasAppliedCompletion,
      cancelCompletionByTask,
      deleteTask,
      // 消息相关
      hasPendingMessages,
      pendingMessageTypes,
      checkPendingMessages,
      hasUserApplied,
      checkUserApplied,
      goToMessages,
      // 用户信息相关
      getUserAvatar,
      getSafeUserAvatar,
      getUserName,
      handleAvatarError,
      handleTaskAvatarError,
      getAvatarUrl, // 从 @/utils/imageUtils.js 导入的函数
      handleRejectCompletion,
      handleApproveCompletion,
      // 组队相关
      showTeamInvitationModal,
      teamInfo,
      teamMembers,
      teamStatus,
      openTeamInvitationModal,
      closeTeamInvitationModal,
      handleTeamInvitationConfirm,
      loadTeamInfo,
      updateTeamName,
      handleUpdateTeamName,
      // 新的组队模式相关
      teamMode,
      teamName,
      editingTeamName,
      userInfoCache,
      canShowTeamMode,
      canShowBadgeAllocation,
      searchKeyword,
      searchResults,
      searchLoading,
      searchError,
      invitedUsers,
      toggleTeamMode,
      checkExistingTeam,
      handleApplication,
      handleTeamApplicationNew,
      showContactLeaderModal,
      selectChallengeType,
      selectTeamRole,
      handleTeamApplication,
      getTeamStatusText,
      formatTime,
      getUserInfo,
      getUserNickname,
      getUserAvatar,
      searchFriends,
      inviteSingleUser,
      markUserAsInvited,
      isUserInvited,
      saveTeamName,
      isTeamLeader,
      removeTeamMember,
      leaveTeam,
      dissolveTeam,
      recreateTeamFromDissolved,
      initiateRemoveMemberVote,
      initiateImpeachLeaderVote,
      transferLeadership,
      voteOnProposal,
      withdrawVote,
      withdrawLoading,
      // 投票相关（任务详情页面）
      activeTeamVotes,
      voteHistory,
      voteLoading,
      selectedCandidateId,
      submitVote,
      submitCandidateVote,
      selectCandidate,
      withdrawVoteFromTask,
      loadTeamVotes,
      loadVoteHistory,
      getVoteTitle,
      getVoteTypeText,
      getVoteRuleText,
      getVoteChoiceText,
      getVoteStatusText,
      getVoteChoiceDetailText,
      formatCountdown,
      // 任务修改相关
      canEditTask,
      goToEditTask,
      showEditTaskModal,
      editTaskForm,
      taskEditInfo,
      openEditTaskModal,
      closeEditTaskModal,
      submitEditTask,
      canSubmitEdit,
      // 任务类型显示
      getTaskTypeText,
      isTeamTask,
      // 添加缺失的属性
      challengeType,
      teamRole,
      isTaskPublisher,
      canEditBadgeAllocation,
      getAvatarDisplayUrl
    };
  }
};
</script>

<style scoped>
/* 主滚动容器 - 撑满整个屏幕 */
.scroll-container {
  height: 100vh;
  width: 100vw;
  background: #f5f5f5;
  margin: 0 auto;
  /* #ifdef APP-PLUS */
  overflow-y: auto;
  -webkit-overflow-scrolling: touch;
  /* #endif */
}

/* 加载和错误状态 */
.loading,
.error {
  text-align: center;
  margin: 20px 0;
  font-size: 1.2rem;
  color: #d63031;
}

/* 头部卡片 - 包含头像、标题、状态、发布者、时间信息 */
.task-header {
  width: calc(100vw - 64px);
  margin: 10px auto;
  display: flex;
  align-items: center;
  background: #fff;
  padding: 16px;
  border-radius: 12px;
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08);
  border: 1px solid rgba(0, 0, 0, 0.05);
}

/* 用户头像 */
.user-avatar {
  width: 50px;
  height: 50px;
  border-radius: 50%;
  margin-right: 20px;
  border: 2px solid #74b9ff;
  object-fit: cover;
  overflow: hidden;
}

/* 头部主要内容区域 */
.header-main {
  flex: 1;
  margin-left: 20px;
  text-align: left;
}

/* 标题和状态标签行 */
.header-title-row {
  display: flex;
  align-items: center;
  margin-bottom: 5px;
}

/* 任务标题 */
.task-title {
  font-size: 18px;
  font-weight: 700;
  color: #2c3e50;
  flex: 1;
  line-height: 1.4;
  margin: 0;
  letter-spacing: -0.2px;
  text-align: left;
}

/* 状态标签 */
.status-tag {
  background-color: #ff9f43;
  color: white;
  padding: 6px 12px;
  border-radius: 12px;
  font-size: 12px;
  font-weight: 600;
  margin-left: 12px;
  letter-spacing: 0.5px;
  text-transform: uppercase;
  box-shadow: 0 2px 4px rgba(255, 159, 67, 0.3);
}

/* 发布信息 */
.task-publisher,
.task-time,
.task-deadline {
  font-size: 13px;
  color: #7f8c8d;
  margin-bottom: 2px;
  font-weight: 400;
  letter-spacing: 0.1px;
  text-align: left;
}

/* 任务详情卡片 - 包含描述、金额、状态等信息 */
.task-body {
  width: calc(100vw - 64px);
  margin: 0 auto 16px auto;
  background: #fff;
  padding: 16px;
  border-radius: 12px;
  line-height: 1.6;
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08);
  border: 1px solid rgba(0, 0, 0, 0.05);
  /* #ifdef APP-PLUS */
  overflow: visible;
  /* #endif */
}

/* 任务信息行 - 标签和值的组合 */
.task-info-row {
  display: flex;
  align-items: flex-start;
  margin-bottom: 12px;
  padding: 8px 0;
  border-bottom: 1px solid rgba(0, 0, 0, 0.05);
}

.task-info-row:last-child {
  border-bottom: none;
  margin-bottom: 0;
}

/* 信息标签 */
.task-info-label {
  font-weight: 600;
  color: #34495e;
  min-width: 80px;
  flex-shrink: 0;
  margin-right: 16px;
  font-size: 14px;
  letter-spacing: 0.3px;
}

/* 信息值 */
.task-info-value {
  color: #2c3e50;
  flex: 1;
  word-break: break-word;
  line-height: 1.6;
  font-size: 14px;
  font-weight: 500;
  letter-spacing: 0.1px;
  text-align: left;
}

/* 地图容器 */
.map-container {
  width: calc(100vw - 64px);
  margin: 0 auto 16px auto;
  text-align: center;
  background: #fff;
  border-radius: 12px;
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08);
  border: 1px solid rgba(0, 0, 0, 0.05);
  padding: 16px;
  position: relative;
  /* #ifdef APP-PLUS */
  z-index: 0;
  overflow: visible;
  /* #endif */
}

/* 地图组件 */
.map {
  width: 100%;
  height: 300px;
  border-radius: 8px;
  border: 2px solid #74b9ff;
  /* #ifdef APP-PLUS */
  position: relative !important;
  overflow: visible !important;
  min-height: 300px !important;
  /* #endif */
}

/* #ifdef APP-PLUS */
.map-wrapper {
  position: relative;
  width: 100%;
  height: 100%;
  pointer-events: none;
}
/* #endif */

/* 定位按钮 */
.move-to-task-btn {
  width: 100%;
  background: #74b9ff;
  color: white;
  border: none;
  border-radius: 12px;
  padding: 14px 20px;
  font-size: 15px;
  line-height: 1.4;
  text-align: center;
  margin: 8px 0;
  cursor: pointer;
  transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
  box-sizing: border-box;
  font-weight: 600;
  letter-spacing: 0.3px;
}

/* 徽章卡片 - 完成任务获得的荣誉 */
.task-badges {
  width: calc(100vw - 64px);
  margin: 0 auto 16px auto;
  background: #fff;
  padding: 16px;
  border-radius: 12px;
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08);
  border: 1px solid rgba(0, 0, 0, 0.05);
}

/* 徽章标题 */
.badge-title {
  font-size: 16px;
  font-weight: 700;
  color: #2c3e50;
  margin-bottom: 12px;
  letter-spacing: -0.1px;
}

/* 单个徽章 */
.badge {
  border: 1px solid #dfe6e9;
  padding: 12px;
  margin-bottom: 12px;
  border-radius: 12px;
  background: linear-gradient(135deg, #ffeaa7, #fab1a0);
  color: #2c3e50;
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
  font-size: 14px;
  font-weight: 600;
  line-height: 1.5;
  letter-spacing: 0.2px;
}

/* 徽章标签 */
.badge-label {
  font-weight: 600;
  color: #2c3e50;
  letter-spacing: 0.3px;
}

/* 申请挑战任务区域 */
.challenge-section {
  width: calc(100vw - 64px);
  margin: 0 auto 16px auto;
  background: #fff;
  padding: 16px;
  border-radius: 12px;
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08);
  border: 1px solid rgba(0, 0, 0, 0.05);
}

/* 申请完成任务区域 */
.apply-complete-section {
  width: calc(100vw - 64px);
  margin: 0 auto 16px auto;
  background: #fff;
  padding: 16px;
  border-radius: 12px;
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08);
  border: 1px solid rgba(0, 0, 0, 0.05);
}

/* 申请完成标题 */
.apply-complete-title {
  font-size: 16px;
  font-weight: 700;
  color: #2c3e50;
  margin-bottom: 16px;
  letter-spacing: -0.1px;
}

/* 表单分组 */
.form-group {
  margin-bottom: 20px;
}

/* 表单标签 */
.form-group text {
  display: block;
  margin-bottom: 8px;
  font-weight: 600;
  color: #34495e;
  font-size: 14px;
  letter-spacing: 0.3px;
}

/* 徽章表单 */
.badge-form {
  background: #fff;
  padding: 20px;
  border-radius: 16px;
  margin-bottom: 18px;
  border: 1px solid #e2e8f0;
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08);
}

/* 让"铭牌描述"输入与下方 UID/角色/贡献比例保持完全一致的外观
   注意：放宽选择器，适配编译后层级（不一定是直系子元素） */
.badge-form input:not([type="hidden"]):not(.wx-hidden),
.badge-form textarea,
.badge-form > view:not(.contributor-form) input:not([type="hidden"]),
.badge-form input.badge-desc,
.badge-form textarea.badge-desc {
  width: 100%;
  padding: 14px 18px !important;
  border: 1px solid #ddd !important;
  border-radius: 16px !important;
  font-size: 16px !important;
  background: #ffffff !important;
  box-sizing: border-box !important;
  margin: 8px 0 12px !important;
  line-height: 1.5 !important;
  letter-spacing: 0.1px !important;
  min-height: 50px !important;
  color: #2c3e50 !important;
  -webkit-text-fill-color: #2c3e50 !important;
  caret-color: #2c3e50 !important;
  -webkit-appearance: none !important;
  appearance: none !important;
  color-scheme: light !important;
}

/* 贡献者表单 */
.contributor-form {
  display: flex;
  flex-direction: column;
  gap: 12px;
  margin-bottom: 18px;
  padding: 14px 12px 16px 12px;
  background: #f8f9fa;
  border-radius: 16px;
  border: 1px solid #e2e8f0;
  /* 某些 iOS 下祖先层的 transform/opacity 会影响文本渲染，强制自身图层 */
  -webkit-transform: translateZ(0);
  transform: translateZ(0);
  /* 触控命中更友好 */
  min-height: 48px;
}

/* 贡献者表单标签 */
.contributor-form text {
  font-size: 14px;
  color: #556;
  margin-bottom: 6px;
  font-weight: 600;
  letter-spacing: 0.2px;
}

/* 贡献者选择器容器 */
.contributor-selector {
  width: 100%;
  margin-bottom: 6px;
}

/* 当前用户显示 */
.current-user-display {
  padding: 12px 16px;
  background: #e8f4fd;
  border: 1px solid #b3d9ff;
  border-radius: 8px;
  text-align: center;
}

.current-user-display text {
  color: #1976d2;
  font-weight: 500;
  font-size: 14px;
}

/* 输入框和文本域 */
input,
textarea,
.challenge-content,
.complete-proof-textarea {
  width: 100%;
  padding: 14px 18px;
  border: 1px solid #ddd;
  border-radius: 16px;
  /* iOS 小于16px聚焦会自动放大，易引发渲染异常 */
  font-size: 16px;
  background: #ffffff;
  box-sizing: border-box;
  margin: 4px 0;
  resize: none;
  transition: all 0.3s ease;
  line-height: 1.5;
  letter-spacing: 0.1px;
  /* 明确指定文本与光标颜色，修复 iOS 深色模式文字不可见 */
  color: #2c3e50 !important;
  -webkit-text-fill-color: #2c3e50 !important;
  caret-color: #2c3e50;
  -webkit-appearance: none;
  appearance: none;
  /* 禁用系统暗色自动反色 */
  color-scheme: light;
}

/* 放大"UID/角色/贡献比例"三个输入框尺寸 */
.contributor-form input,
.contributor-form textarea {
  min-height: 50px;
  line-height: 1.6;
  padding: 14px 18px;
  border-radius: 16px;
}

/* 输入框焦点状态 */
input:focus,
textarea:focus,
.challenge-content:focus,
.complete-proof-textarea:focus {
  border-color: #6c5ce7;
  outline: none;
  box-shadow: 0 0 0 2px rgba(108, 92, 231, 0.1);
  /* 避免某些 iOS 机型在 transform 下触发文本绘制异常 */
  /* transform: translateY(-1px); */
  background: #ffffff !important;
  color: #2c3e50 !important;
  -webkit-text-fill-color: #2c3e50 !important;
  /* 让焦点态也更容易点击 */
  min-height: 50px;
}

/* 占位符颜色，防止深色模式下过浅 */
input::placeholder,
textarea::placeholder {
  color: #95a5a6 !important;
  opacity: 1;
}

/* 禁用状态 */
input[disabled],
textarea[disabled] {
  background: #f5f5f5;
  color: #999;
}

/* 挑战内容容器 */
.challenge-content-container {
  position: relative;
  width: 100%;
  margin-top: 1rem;
}

/* 挑战内容文本域 */
.challenge-content {
  min-height: 96px;
}

/* 完成证明容器 */
.complete-proof-container {
  position: relative;
  width: 100%;
  margin-top: 1rem;
}

/* 完成证明文本域 */
.complete-proof-textarea {
  min-height: 112px;
}

/* 字符计数器 */
.character-counter {
  position: absolute;
  right: 1rem;
  bottom: 1rem;
  font-size: 12px;
  color: #7f8c8d;
  background: rgba(255, 255, 255, 0.95);
  padding: 4px 8px;
  border-radius: 8px;
  box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
  font-weight: 500;
  letter-spacing: 0.2px;
}

/* 百分比总计 */
.percentage-total {
  margin: 12px 0;
  font-weight: 600;
  font-size: 14px;
  color: #2c3e50;
  letter-spacing: 0.2px;
}

/* 错误文本 */
.error-text {
  color: #e74c3c;
  font-weight: 500;
  font-size: 13px;
  letter-spacing: 0.1px;
}

/* 按钮基础样式 */
.challenge-btn,
.apply-complete-btn,
.add-btn,
.remove-btn {
  width: 100%;
  background: #74b9ff;
  color: white;
  border: none;
  border-radius: 12px;
  padding: 14px 20px;
  font-size: 15px;
  line-height: 1.4;
  text-align: center;
  margin: 8px 0;
  cursor: pointer;
  transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
  box-sizing: border-box;
  font-weight: 600;
  letter-spacing: 0.3px;
}

/* 按钮悬停效果 */
.move-to-task-btn:hover,
.challenge-btn:hover,
.apply-complete-btn:hover,
.add-btn:hover {
  background: #0984e3;
  /* iOS 输入聚焦期间移除位移动画，避免文本闪烁 */
  /* transform: translateY(-2px); */
  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
}

/* 挑战按钮特殊样式 */
.challenge-btn {
  background: #6c5ce7;
  font-weight: bold;
  margin-top: 15px;
  box-shadow: 0 2px 8px rgba(108, 92, 231, 0.3);
}

/* 申请完成按钮特殊样式 */
.apply-complete-btn {
  background: #00b894;
  font-weight: bold;
  margin-top: 15px;
  box-shadow: 0 2px 8px rgba(0, 184, 148, 0.3);
}

/* 删除按钮特殊样式 */
.remove-btn {
  background: #ff7675;
  padding: 8px 15px;
  font-size: 14px;
  box-shadow: 0 2px 8px rgba(255, 118, 117, 0.3);
}

/* 添加按钮特殊样式 */
.add-btn {
  margin-top: 10px;
}

/* 统一"铭牌描述"输入为与"贡献比例(%)"完全一致的样式 */
.badge-form .badge-desc-input,
.badge-form > input:not([type="hidden"]),
.badge-form view > input:not([type="hidden"]),
.badge-form input[type="text"],
.badge-form input[type="number"] {
  width: 100% !important;
  padding: 14px 18px !important;
  border: 1px solid #ddd !important;
  border-radius: 16px !important;
  font-size: 16px !important;
  background: #ffffff !important;
  box-sizing: border-box !important;
  margin: 8px 0 12px !important;
  line-height: 1.5 !important;
  letter-spacing: 0.1px !important;
  min-height: 50px !important;
  color: #2c3e50 !important;
  -webkit-text-fill-color: #2c3e50 !important;
  caret-color: #2c3e50 !important;
  -webkit-appearance: none !important;
  appearance: none !important;
  color-scheme: light !important;
}
</style>
<style scoped>
/* 工作记录区块 */
.work-records {
  width: calc(100vw - 64px);
  margin: 0 auto 16px auto;
  background: #fff;
  padding: 16px;
  border-radius: 12px;
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08);
  border: 1px solid rgba(0, 0, 0, 0.05);
}

.work-section-title {
  font-size: 16px;
  font-weight: 700;
  color: #2c3e50;
  margin-bottom: 12px;
}

.work-item {
  border: 1px solid #e2e8f0;
  border-radius: 12px;
  padding: 12px;
  margin-bottom: 10px;
  background: #fafafa;
}

.work-item-row {
  display: flex;
  align-items: center;
  margin-bottom: 6px;
}

.work-item-row:last-child {
  margin-bottom: 0;
}

.work-item-label {
  min-width: 48px;
  color: #34495e;
  font-weight: 600;
  margin-right: 12px;
}

.work-item-value {
  flex: 1;
  color: #2c3e50;
}

.empty-records {
  color: #7f8c8d;
}

/* 工作操作按钮区块 */
.work-actions {
  width: calc(100vw - 64px);
  margin: 0 auto 16px auto;
  background: #fff;
  padding: 16px;
  border-radius: 12px;
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08);
  border: 1px solid rgba(0, 0, 0, 0.05);
}

.start-work-btn {
  background: #0984e3;
}

.end-work-btn {
  background: #e17055;
}

/* 任务操作按钮区域 */
.task-actions {
  width: calc(100vw - 64px);
  margin: 0 auto 16px auto;
  background: #fff;
  padding: 16px;
  border-radius: 12px;
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08);
  border: 1px solid rgba(0, 0, 0, 0.05);
  display: flex;
  flex-direction: column;
  gap: 12px;
}

.cancel-apply-btn {
  background: #ff7675;
  color: white;
  border: none;
  border-radius: 12px;
  padding: 14px 20px;
  font-size: 15px;
  font-weight: 600;
  text-align: center;
  cursor: pointer;
  transition: all 0.3s ease;
}

.request-cancel-btn {
  background: #fdcb6e;
  color: white;
  border: none;
  border-radius: 12px;
  padding: 14px 20px;
  font-size: 15px;
  font-weight: 600;
  text-align: center;
  cursor: pointer;
  transition: all 0.3s ease;
}

.delete-task-btn {
  background: #e17055;
  color: white;
  border: none;
  border-radius: 12px;
  padding: 14px 20px;
  font-size: 15px;
  font-weight: 600;
  text-align: center;
  cursor: pointer;
  transition: all 0.3s ease;
}

/* 弹窗样式 */
.modal-overlay {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  background: rgba(0, 0, 0, 0.5);
  display: flex;
  align-items: center;
  justify-content: center;
  z-index: 1000;
}

.modal-content {
  background: white;
  border-radius: 16px;
  width: 90%;
  max-width: 500px;
  max-height: 80vh;
  overflow: hidden;
  box-shadow: 0 10px 30px rgba(0, 0, 0, 0.3);
}

.modal-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 20px;
  border-bottom: 1px solid #e2e8f0;
}

.modal-title {
  font-size: 18px;
  font-weight: 700;
  color: #2c3e50;
}

.modal-close {
  background: none;
  border: none;
  font-size: 24px;
  color: #7f8c8d;
  cursor: pointer;
  padding: 0;
  width: 30px;
  height: 30px;
  display: flex;
  align-items: center;
  justify-content: center;
}

.modal-body {
  padding: 20px;
}

.modal-footer {
  display: flex;
  gap: 12px;
  padding: 20px;
  border-top: 1px solid #e2e8f0;
}

.modal-cancel-btn {
  flex: 1;
  background: #95a5a6;
  color: white;
  border: none;
  border-radius: 12px;
  padding: 14px 20px;
  font-size: 15px;
  font-weight: 600;
  text-align: center;
  cursor: pointer;
  transition: all 0.3s ease;
}

.modal-confirm-btn {
  flex: 1;
  background: #74b9ff;
  color: white;
  border: none;
  border-radius: 12px;
  padding: 14px 20px;
  font-size: 15px;
  font-weight: 600;
  text-align: center;
  cursor: pointer;
  transition: all 0.3s ease;
}

.modal-confirm-btn:disabled {
  background: #bdc3c7;
  cursor: not-allowed;
}

.cancel-reason-textarea {
  min-height: 100px;
  width: 100%;
  padding: 14px 18px;
  border: 1px solid #ddd;
  border-radius: 12px;
  font-size: 16px;
  background: #ffffff;
  box-sizing: border-box;
  margin: 8px 0;
  resize: none;
  transition: all 0.3s ease;
  line-height: 1.5;
  color: #2c3e50;
  -webkit-text-fill-color: #2c3e50;
  caret-color: #2c3e50;
  -webkit-appearance: none;
  appearance: none;
  color-scheme: light;
}

.cancel-reason-textarea:focus {
  border-color: #6c5ce7;
  outline: none;
  box-shadow: 0 0 0 2px rgba(108, 92, 231, 0.1);
  background: #ffffff;
  color: #2c3e50;
  -webkit-text-fill-color: #2c3e50;
}

/* 待处理消息样式 */
.pending-messages {
  background: #fff3cd;
  border: 1px solid #ffeaa7;
  border-radius: 12px;
  padding: 16px;
  margin-top: 12px;
}

.pending-title {
  font-size: 16px;
  font-weight: 700;
  color: #856404;
  margin-bottom: 8px;
  display: block;
}

.pending-item {
  margin-bottom: 4px;
}

.pending-item text {
  font-size: 14px;
  color: #856404;
  font-weight: 500;
}

.view-messages-btn {
  background: #fdcb6e;
  color: white;
  border: none;
  border-radius: 12px;
  padding: 12px 20px;
  font-size: 14px;
  font-weight: 600;
  text-align: center;
  cursor: pointer;
  transition: all 0.3s ease;
  margin-top: 12px;
  width: 100%;
}

.view-messages-btn:hover {
  background: #e17055;
  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
}


.preview-proof {
  background: #f8f9fa;
  border: 1px solid #e2e8f0;
  border-radius: 8px;
  padding: 12px;
  margin-top: 8px;
  font-size: 14px;
  line-height: 1.5;
  color: #2c3e50;
  min-height: 60px;
}

.badge-header {
  font-size: 16px;
  font-weight: 600;
  color: #2c3e50;
  margin-bottom: 12px;
  padding: 8px 0;
  border-bottom: 1px solid #e2e8f0;
}

.contributors-list {
  margin-bottom: 20px;
}

.contributor-item {
  margin-bottom: 12px;
}

.contributor-info {
  display: flex;
  align-items: center;
  padding: 12px;
  background: #f8f9fa;
  border-radius: 8px;
  border: 1px solid #e2e8f0;
}

.contributor-avatar {
  width: 40px;
  height: 40px;
  border-radius: 50%;
  margin-right: 12px;
  object-fit: cover;
  border: 2px solid #e2e8f0;
}

.contributor-details {
  flex: 1;
  display: flex;
  flex-direction: column;
}

.contributor-name {
  font-size: 14px;
  font-weight: 600;
  color: #2c3e50;
  margin-bottom: 2px;
}

.contributor-role {
  font-size: 12px;
  color: #7f8c8d;
}

.contributor-percentage {
  font-size: 16px;
  font-weight: 700;
  color: #74b9ff;
}

.contributor-avatar-small {
  width: 24px;
  height: 24px;
  border-radius: 50%;
  margin-right: 8px;
  object-fit: cover;
  border: 1px solid #e2e8f0;
}

.preview-field {
  background: #f8f9fa;
  border: 1px solid #e2e8f0;
  border-radius: 6px;
  padding: 8px 12px;
  font-size: 14px;
  color: #2c3e50;
  min-height: 20px;
  display: flex;
  align-items: center;
}

.preview-actions {
  display: flex;
  gap: 12px;
  padding: 20px;
  border-top: 1px solid #e2e8f0;
  background: #f8f9fa;
}

.reject-btn {
  flex: 1;
  background: #e74c3c;
  color: white;
  border: none;
  border-radius: 12px;
  padding: 14px 20px;
  font-size: 15px;
  font-weight: 600;
  text-align: center;
  cursor: pointer;
  transition: all 0.3s ease;
}

.reject-btn:hover {
  background: #c0392b;
  box-shadow: 0 4px 12px rgba(231, 76, 60, 0.3);
}

.approve-btn {
  flex: 1;
  background: #27ae60;
  color: white;
  border: none;
  border-radius: 12px;
  padding: 14px 20px;
  font-size: 15px;
  font-weight: 600;
  text-align: center;
  cursor: pointer;
  transition: all 0.3s ease;
}

.approve-btn:hover {
  background: #229954;
  box-shadow: 0 4px 12px rgba(39, 174, 96, 0.3);
}

/* 申请完成详情预览样式（复制申请完成样式） */
.apply-complete-preview-section {
  background: #f8f9fa;
  border-radius: 12px;
  padding: 20px;
  margin: 16px;
  border: 1px solid #e2e8f0;
}

/* 预览字段样式 */
.preview-proof {
  background: #f8f9fa;
  border: 1px solid #e2e8f0;
  border-radius: 8px;
  padding: 12px;
  margin-top: 8px;
  min-height: 60px;
  font-size: 14px;
  color: #2c3e50;
  line-height: 1.5;
}

.preview-field {
  background: #f8f9fa;
  border: 1px solid #e2e8f0;
  border-radius: 6px;
  padding: 8px 12px;
  font-size: 14px;
  color: #2c3e50;
  min-height: 20px;
  display: flex;
  align-items: center;
}

/* 申请完成处理按钮样式（弹窗内） */
.completion-actions {
  display: flex;
  gap: 12px;
  padding: 20px;
  border-top: 1px solid #e2e8f0;
  background: #f8f9fa;
  position: sticky;
  bottom: 0;
  z-index: 10;
}

/* 申请完成处理按钮样式（页面底部） */
.completion-actions-bottom {
  display: flex;
  gap: 12px;
  padding: 20px;
  background: #f8f9fa;
  border-top: 1px solid #e2e8f0;
  position: sticky;
  bottom: 0;
  z-index: 100;
}

.reject-completion-btn {
  flex: 1;
  background: #e74c3c;
  color: white;
  border: none;
  border-radius: 12px;
  padding: 14px 20px;
  font-size: 15px;
  font-weight: 600;
  text-align: center;
  cursor: pointer;
  transition: all 0.3s ease;
}

.reject-completion-btn:hover {
  background: #c0392b;
  box-shadow: 0 4px 12px rgba(231, 76, 60, 0.3);
}

.approve-completion-btn {
  flex: 1;
  background: #27ae60;
  color: white;
  border: none;
  border-radius: 12px;
  padding: 14px 20px;
  font-size: 15px;
  font-weight: 600;
  text-align: center;
  cursor: pointer;
  transition: all 0.3s ease;
}

.approve-completion-btn:hover {
  background: #229954;
  box-shadow: 0 4px 12px rgba(39, 174, 96, 0.3);
}

/* 申请方式选择 */
.application-methods {
  margin-top: 16px;
}

.individual-btn {
  flex: 1;
  background: #4A90E2;
  color: white;
  border: none;
  border-radius: 12px;
  padding: 14px 20px;
  font-size: 15px;
  font-weight: 600;
  text-align: center;
  cursor: pointer;
  transition: all 0.3s ease;
}

.individual-btn:hover {
  background: #357ABD;
  box-shadow: 0 4px 12px rgba(74, 144, 226, 0.3);
}

.team-btn {
  flex: 1;
  background: #9B59B6;
  color: white;
  border: none;
  border-radius: 12px;
  padding: 14px 20px;
  font-size: 15px;
  font-weight: 600;
  text-align: center;
  cursor: pointer;
  transition: all 0.3s ease;
}

.team-btn:hover {
  background: #8E44AD;
  box-shadow: 0 4px 12px rgba(155, 89, 182, 0.3);
}

/* 申请模式选择样式 */
.application-mode-selection {
  margin-bottom: 16px;
  padding: 12px 16px;
  background: #f8f9fa;
  border-radius: 8px;
  border: 1px solid #e9ecef;
  display: inline-block;
  width: auto;
  max-width: 200px;
}

.mode-option {
  display: flex;
  align-items: center;
  gap: 8px;
  cursor: pointer;
}

.mode-checkbox {
  width: 18px;
  height: 18px;
}

.mode-label {
  font-size: 16px;
  font-weight: 500;
  color: #333;
}

/* 组队申请表单样式 */
.team-application-form {
  margin-top: 16px;
  padding: 16px;
  background: #f8f9fa;
  border-radius: 8px;
  border: 1px solid #e9ecef;
}

/* 投票相关样式 */
.active-votes-section {
  margin-bottom: 16px;
  padding: 12px;
  background: #fff3cd;
  border-radius: 6px;
  border: 1px solid #ffeaa7;
}

.votes-list {
  margin-top: 10px;
}

.vote-item {
  background: white;
  border-radius: 8px;
  padding: 15px;
  margin-bottom: 10px;
  border: 1px solid #e9ecef;
  box-shadow: 0 2px 4px rgba(0,0,0,0.1);
}

.vote-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-bottom: 10px;
}

.vote-title {
  font-size: 16px;
  font-weight: bold;
  color: #2c3e50;
}

.vote-type {
  font-size: 12px;
  color: #6c757d;
  background: #e9ecef;
  padding: 2px 8px;
  border-radius: 4px;
}

.vote-content {
  margin-bottom: 10px;
}

.vote-reason, .vote-initiator, .vote-target {
  display: block;
  font-size: 14px;
  color: #495057;
  margin-bottom: 5px;
}

.vote-progress {
  margin-bottom: 15px;
}

.progress-text {
  font-size: 14px;
  color: #6c757d;
  margin-bottom: 5px;
}

.progress-bar {
  width: 100%;
  height: 8px;
  background: #e9ecef;
  border-radius: 4px;
  overflow: hidden;
}

.progress-fill {
  height: 100%;
  background: linear-gradient(90deg, #28a745, #20c997);
  transition: width 0.3s ease;
}

.vote-actions {
  display: flex;
  gap: 10px;
}

.vote-btn {
  flex: 1;
  padding: 8px 16px;
  border: none;
  border-radius: 4px;
  font-size: 14px;
  cursor: pointer;
  transition: all 0.3s ease;
}

.approve-btn {
  background: #28a745;
  color: white;
}

.approve-btn:hover {
  background: #218838;
}

.reject-btn {
  background: #dc3545;
  color: white;
}

.reject-btn:hover {
  background: #c82333;
}

.vote-status {
  text-align: center;
  padding: 10px;
  background: #f8f9fa;
  border-radius: 4px;
}

.voted-status {
  font-size: 14px;
  color: #6c757d;
}

/* 投票结果显示 */
.vote-results {
  display: flex;
  flex-direction: column;
  gap: 8px;
  margin: 12px 0;
}

.result-item {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 8px 12px;
  background: #f8f9fa;
  border-radius: 6px;
  border-left: 3px solid #dee2e6;
}

.result-label {
  font-weight: 600;
  color: #495057;
}

.result-count {
  font-weight: 600;
  font-size: 16px;
}

.result-count.approve {
  color: #28a745;
}

.result-count.reject {
  color: #dc3545;
}

.result-count.pending {
  color: #6c757d;
}

.team-info-section, .team-members-section, .pending-invitations-section {
  margin-bottom: 16px;
  padding: 12px;
  background: #fff;
  border-radius: 6px;
  border: 1px solid #e9ecef;
}

/* 解散团队按钮样式 */
.dissolve-team-section {
  margin-top: 16px;
  text-align: center;
}

.dissolve-team-btn {
  background: linear-gradient(135deg, #ff6b6b 0%, #ee5a52 100%);
  color: white;
  border: none;
  border-radius: 8px;
  padding: 12px 24px;
  font-size: 14px;
  font-weight: 600;
  box-shadow: 0 4px 12px rgba(255, 107, 107, 0.3);
  transition: all 0.3s ease;
}

.dissolve-team-btn:active {
  transform: translateY(1px);
  box-shadow: 0 2px 8px rgba(255, 107, 107, 0.4);
}

.section-title {
  font-size: 16px;
  font-weight: 600;
  color: #333;
  margin-bottom: 12px;
  display: block;
}

.team-info-item {
  margin-bottom: 12px;
  display: flex;
  align-items: center;
  gap: 8px;
}

.info-label {
  font-size: 14px;
  font-weight: 500;
  color: #666;
  min-width: 80px;
}

.info-value {
  font-size: 14px;
  color: #333;
}

.recreate-btn {
  padding: 6px 12px;
  background: #4CAF50;
  color: white;
  border: none;
  border-radius: 4px;
  font-size: 12px;
  font-weight: 500;
  cursor: pointer;
  transition: background 0.3s ease;
  margin-left: 8px;
}

.recreate-btn:hover {
  background: #45a049;
}

.dissolved-hint {
  margin: 10px 0;
  padding: 10px;
  background: #fff3e0;
  border: 1px solid #ff9800;
  border-radius: 6px;
  text-align: center;
}

.dissolved-hint text {
  color: #f57c00;
  font-size: 14px;
}

.team-name-edit {
  display: flex;
  align-items: center;
  gap: 8px;
  width: 100%;
  margin-top: 6px;
}

.team-name-input {
  flex: 1;
  padding: 10px 12px !important;
  border: 1px solid #ddd !important;
  border-radius: 6px !important;
  font-size: 14px !important;
  min-height: 36px !important;
  width: 100% !important;
  box-sizing: border-box !important;
  background: #ffffff !important;
  color: #2c3e50 !important;
  -webkit-text-fill-color: #2c3e50 !important;
  caret-color: #2c3e50 !important;
  -webkit-appearance: none !important;
  appearance: none !important;
  color-scheme: light !important;
}

.save-name-btn {
  padding: 10px 16px;
  background: #4CAF50;
  color: white;
  border: none;
  border-radius: 6px;
  font-size: 13px;
  font-weight: 500;
  cursor: pointer;
  transition: background 0.3s ease;
  min-width: 60px;
  white-space: nowrap;
  height: 36px;
}

.save-name-btn:hover:not(:disabled) {
  background: #45a049;
}

.save-name-btn:disabled {
  background: #ccc;
  cursor: not-allowed;
}

/* 成员列表样式 */
.members-list, .invitations-list {
  display: flex;
  flex-direction: column;
  gap: 8px;
}

.member-item, .invitation-item {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 8px;
  background: #f8f9fa;
  border-radius: 6px;
  border: 1px solid #e9ecef;
}

.member-avatar, .invitation-avatar {
  width: 32px;
  height: 32px;
  border-radius: 50%;
  object-fit: cover;
}

.member-info, .invitation-info {
  flex: 1;
  display: flex;
  flex-direction: column;
  gap: 2px;
}

.member-name, .invitation-name {
  font-size: 14px;
  font-weight: 500;
  color: #333;
}

.member-role {
  font-size: 12px;
  color: #666;
}

.member-status {
  font-size: 12px;
  padding: 2px 6px;
  border-radius: 3px;
  font-weight: 500;
}

.status-0 {
  background: #fff3cd;
  color: #856404;
}

.status-1 {
  background: #d4edda;
  color: #155724;
}

.status-2 {
  background: #f8d7da;
  color: #721c24;
}

.status-3 {
  background: #d1ecf1;
  color: #0c5460;
}

.invitation-time {
  font-size: 12px;
  color: #999;
}

/* 成员操作按钮样式 */
.member-actions {
  display: flex;
  gap: 8px;
}

.remove-member-btn, .leave-team-btn {
  padding: 6px 12px;
  border-radius: 4px;
  font-size: 12px;
  font-weight: 500;
  border: none;
  cursor: pointer;
  transition: all 0.3s ease;
}

.remove-member-btn {
  background: #dc3545;
  color: white;
}

.remove-member-btn:hover {
  background: #c82333;
}

.leave-team-btn {
  background: #6c757d;
  color: white;
}

.leave-team-btn:hover {
  background: #5a6268;
}

.vote-remove-btn {
  background: #fa8c16;
  color: white;
}

.vote-remove-btn:hover {
  background: #d46b08;
}

.impeach-leader-btn {
  background: #f5222d;
  color: white;
}

.impeach-leader-btn:hover {
  background: #cf1322;
}

.transfer-leader-btn {
  background: #722ed1;
  color: white;
}

.transfer-leader-btn:hover {
  background: #531dab;
}

/* 挑战类型选择样式 */
.challenge-type-selection {
  margin-bottom: 20px;
}

.selection-title {
  font-size: 16px;
  font-weight: 600;
  color: #333;
  margin-bottom: 12px;
  display: block;
}

.challenge-options {
  display: flex;
  gap: 12px;
  flex-wrap: wrap;
}

.challenge-option {
  flex: 1;
  min-width: 200px;
  border: 2px solid #e8e8e8;
  border-radius: 12px;
  padding: 16px;
  cursor: pointer;
  transition: all 0.3s ease;
  background: #fff;
}

.challenge-option:hover {
  border-color: #4A90E2;
  box-shadow: 0 2px 8px rgba(74, 144, 226, 0.1);
}

.challenge-option.selected {
  border-color: #4A90E2;
  background: #f0f7ff;
  box-shadow: 0 2px 8px rgba(74, 144, 226, 0.2);
}

.option-header {
  display: flex;
  align-items: center;
  margin-bottom: 8px;
}

.option-icon {
  font-size: 24px;
  margin-right: 8px;
}

.team-icon {
  color: #1890ff;
}

.option-title {
  font-size: 16px;
  font-weight: 600;
  color: #333;
  flex: 1;
}

.option-badge {
  background: #4A90E2;
  color: white;
  padding: 2px 8px;
  border-radius: 12px;
  font-size: 12px;
  font-weight: 500;
}

.option-description {
  font-size: 14px;
  color: #666;
  margin-bottom: 12px;
  line-height: 1.4;
}

.option-features {
  display: flex;
  flex-direction: column;
  gap: 4px;
}

.feature-item {
  font-size: 12px;
  color: #52c41a;
  font-weight: 500;
}

/* 团队角色选择样式 */
.team-role-selection {
  margin-top: 20px;
  padding: 16px;
  background: #f8f9fa;
  border-radius: 12px;
  border: 1px solid #e8e8e8;
}

.role-selection-title {
  font-size: 15px;
  font-weight: 600;
  color: #333;
  margin-bottom: 12px;
  display: block;
}

.role-options {
  display: flex;
  gap: 12px;
  flex-wrap: wrap;
}

.role-option {
  flex: 1;
  min-width: 180px;
  border: 2px solid #e8e8e8;
  border-radius: 10px;
  padding: 14px;
  cursor: pointer;
  transition: all 0.3s ease;
  background: #fff;
}

.role-option:hover {
  border-color: #4A90E2;
  box-shadow: 0 2px 6px rgba(74, 144, 226, 0.1);
}

.role-option.selected {
  border-color: #4A90E2;
  background: #f0f7ff;
  box-shadow: 0 2px 6px rgba(74, 144, 226, 0.2);
}

.role-header {
  display: flex;
  align-items: center;
  margin-bottom: 6px;
}

.role-icon {
  font-size: 20px;
  margin-right: 6px;
}

.leader-icon {
  color: #fa8c16;
}

.member-icon {
  color: #52c41a;
}

.role-title {
  font-size: 14px;
  font-weight: 600;
  color: #333;
  flex: 1;
}

.role-badge {
  background: #4A90E2;
  color: white;
  padding: 2px 6px;
  border-radius: 10px;
  font-size: 10px;
  font-weight: 500;
}

.role-description {
  font-size: 12px;
  color: #666;
  margin-bottom: 8px;
  line-height: 1.3;
}

.role-responsibilities {
  display: flex;
  flex-direction: column;
  gap: 2px;
}

.responsibility-item {
  font-size: 11px;
  color: #52c41a;
  font-weight: 500;
}

/* 申请按钮样式 */
.application-buttons {
  margin-top: 20px;
}

.team-apply-btn {
  background: linear-gradient(135deg, #1890ff, #40a9ff);
  color: white;
  border: none;
  border-radius: 8px;
  padding: 12px 24px;
  font-size: 16px;
  font-weight: 600;
  width: 100%;
  transition: all 0.3s ease;
}

.team-apply-btn:hover {
  background: linear-gradient(135deg, #096dd9, #1890ff);
  transform: translateY(-1px);
  box-shadow: 0 4px 12px rgba(24, 144, 255, 0.3);
}

.contact-leader-btn {
  background: #722ed1;
  color: white;
  border: none;
  border-radius: 6px;
  padding: 8px 16px;
  font-size: 14px;
  margin-top: 8px;
  transition: all 0.3s ease;
}

.contact-leader-btn:hover {
  background: #531dab;
  transform: translateY(-1px);
}

/* 好友搜索区域样式 */
.friend-search-section {
  margin-top: 8px;
}

.search-input-group {
  display: flex;
  gap: 8px;
  margin-bottom: 16px;
}

.search-input {
  flex: 1;
  border: 1px solid #ddd;
  border-radius: 8px;
  padding: 14px 16px;
  font-size: 16px;
  min-height: 48px;
}

.search-btn {
  background: #4A90E2;
  color: white;
  border: none;
  border-radius: 8px;
  padding: 14px 24px;
  font-size: 16px;
  cursor: pointer;
  min-height: 48px;
  white-space: nowrap;
}

.search-loading, .search-error, .search-empty, .search-placeholder {
  text-align: center;
  color: #666;
  padding: 20px;
}

.search-error {
  color: #e74c3c;
}

.search-results {
  max-height: 300px;
  overflow-y: auto;
}

.search-result-item {
  display: flex;
  align-items: center;
  padding: 12px;
  border-bottom: 1px solid #f5f5f5;
  cursor: pointer;
  transition: background-color 0.2s;
}

.search-result-item:hover {
  background: #f8f9fa;
}

.search-result-item.already-selected {
  background: #e8f5e8;
  color: #2e7d32;
}

.search-friend-avatar {
  width: 40px;
  height: 40px;
  border-radius: 50%;
  margin-right: 12px;
  object-fit: cover;
}

.search-friend-info {
  flex: 1;
  display: flex;
  flex-direction: column;
}

.friend-name-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: 2px;
}

.search-friend-name {
  font-size: 15px;
  font-weight: 500;
  color: #333;
}

.friend-status-badge {
  padding: 2px 8px;
  border-radius: 12px;
  font-size: 10px;
  font-weight: 500;
}

.friend-status-badge.accepted {
  background: #e8f5e8;
  color: #2e7d32;
}

.friend-status-badge.pending {
  background: #fff3e0;
  color: #f57c00;
}

.friend-status-badge.not_friend {
  background: #f3e5f5;
  color: #7b1fa2;
}

.status-text {
  font-size: 10px;
  font-weight: 500;
}

.search-friend-uid {
  font-size: 12px;
  color: #666;
}

.search-result-actions {
  display: flex;
  flex-direction: column;
  gap: 4px;
  align-items: flex-end;
}

.invite-btn, .add-btn {
  padding: 4px 12px;
  border: none;
  border-radius: 4px;
  font-size: 12px;
  cursor: pointer;
  transition: all 0.3s ease;
}

.invite-btn {
  background: #4CAF50;
  color: white;
}

.invite-btn:hover {
  background: #45a049;
}

.add-btn {
  background: #2196F3;
  color: white;
}

.add-btn:hover {
  background: #1976D2;
}

.invited-status, .added-status {
  padding: 4px 8px;
  border-radius: 4px;
  font-size: 10px;
  text-align: center;
}

.invited-status {
  background: #e8f5e8;
  color: #2e7d32;
}

.added-status {
  background: #e3f2fd;
  color: #1976d2;
}

.invited-text, .added-text {
  font-size: 10px;
  font-weight: 500;
}


/* 团队名称显示样式 */
.team-name-display {
  display: flex;
  flex-direction: column;
  gap: 4px;
}

.team-name-text {
  font-size: 16px;
  color: #333;
  font-weight: 500;
}

.role-hint {
  font-size: 12px;
  color: #999;
}

/* 已解散团队样式 */
.dissolved-team-section {
  background: #fff3e0;
  border: 2px solid #ff9800;
  border-radius: 12px;
  padding: 24px;
  text-align: center;
  margin: 20px 0;
}

.dissolved-info {
  margin-bottom: 20px;
}

.dissolved-title {
  display: block;
  font-size: 18px;
  font-weight: 600;
  color: #f57c00;
  margin-bottom: 8px;
}

.dissolved-desc {
  display: block;
  font-size: 14px;
  color: #e65100;
}

.debug-info {
  display: block;
  font-size: 12px;
  color: #666;
  margin-top: 8px;
}

.recreate-team-btn {
  width: 100%;
  height: 48px;
  background: #ff9800;
  color: white;
  border-radius: 8px;
  font-size: 16px;
  font-weight: 600;
  border: none;
  cursor: pointer;
  transition: all 0.3s ease;
  position: relative;
  z-index: 10;
  display: flex;
  align-items: center;
  justify-content: center;
  margin: 10px 0;
  text-align: center;
}

.recreate-team-btn:hover {
  background: #f57c00;
  box-shadow: 0 4px 12px rgba(255, 152, 0, 0.3);
}

/* 队员提示样式 */
.member-notice {
  display: flex;
  flex-direction: column;
  align-items: center;
  padding: 20px;
  background-color: #f8f9fa;
  border-radius: 8px;
  margin-top: 10px;
}

/* 团队信息显示样式 */
.team-info-section {
  margin: 16px 0;
  padding: 16px;
  background: #f8f9fa;
  border-radius: 12px;
  border: 1px solid #e9ecef;
}

.section-title {
  font-size: 16px;
  font-weight: 600;
  color: #2c3e50;
  margin-bottom: 12px;
  display: block;
}

.members-list {
  display: flex;
  flex-direction: column;
  gap: 12px;
}

.member-item {
  display: flex;
  align-items: center;
  padding: 12px;
  background: white;
  border-radius: 8px;
  border: 1px solid #e9ecef;
  box-shadow: 0 2px 4px rgba(0, 0, 0, 0.05);
}

.member-avatar {
  width: 40px;
  height: 40px;
  border-radius: 50%;
  margin-right: 12px;
  border: 2px solid #e9ecef;
}

.member-info {
  flex: 1;
  display: flex;
  flex-direction: column;
  gap: 4px;
}

.member-name {
  font-size: 14px;
  font-weight: 600;
  color: #2c3e50;
}

.member-role {
  font-size: 12px;
  color: #6c757d;
  background: #e9ecef;
  padding: 2px 8px;
  border-radius: 12px;
  display: inline-block;
  width: fit-content;
}

.member-status {
  font-size: 12px;
  padding: 2px 6px;
  border-radius: 8px;
  display: inline-block;
  width: fit-content;
}

.status-1 {
  background: #d4edda;
  color: #155724;
}

.status-0 {
  background: #f8d7da;
  color: #721c24;
}

.no-team-info {
  padding: 20px;
  text-align: center;
  background: white;
  border-radius: 8px;
  border: 1px solid #e9ecef;
}

.no-team-text {
  color: #6c757d;
  font-size: 14px;
}

.notice-text {
  font-size: 16px;
  color: #666;
  font-weight: 500;
}

.notice-hint {
  font-size: 14px;
  color: #999;
  margin-top: 4px;
}

/* 申请按钮样式 */
.apply-btn {
  background: #6c5ce7;
  color: white;
  border: none;
  border-radius: 12px;
  padding: 14px 20px;
  font-size: 15px;
  font-weight: 600;
  text-align: center;
  cursor: pointer;
  transition: all 0.3s ease;
  width: 100%;
  margin-top: 20px;
}

.apply-btn:hover:not(:disabled) {
  background: #5a4fcf;
  box-shadow: 0 4px 12px rgba(108, 92, 231, 0.3);
}

.apply-btn:disabled {
  background: #ccc;
  cursor: not-allowed;
}

/* 进行中的投票区域样式 */
.active-votes-section-main {
  width: calc(100vw - 64px);
  margin: 10px auto;
  background: #fff;
  padding: 16px;
  border-radius: 12px;
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08);
  border: 1px solid rgba(0, 0, 0, 0.05);
}

.votes-list-main {
  display: flex;
  flex-direction: column;
  gap: 16px;
}

.vote-item-main {
  padding: 16px;
  background: #f8f9fa;
  border-radius: 8px;
  border: 1px solid #e9ecef;
}

.vote-header-main {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-bottom: 12px;
}

.vote-title-main {
  font-size: 16px;
  font-weight: 600;
  color: #2c3e50;
}

.vote-type-badge {
  padding: 4px 12px;
  border-radius: 12px;
  font-size: 12px;
  font-weight: 500;
}

.vote-type-badge.type-1 {
  background: #ffe0e0;
  color: #d63031;
}

.vote-type-badge.type-2 {
  background: #fff3cd;
  color: #856404;
}

.vote-type-badge.type-3 {
  background: #d1ecf1;
  color: #0c5460;
}

.vote-content-main {
  display: flex;
  flex-direction: column;
  gap: 6px;
  margin-bottom: 12px;
}

.vote-reason-text,
.vote-info-text,
.vote-deadline-text {
  font-size: 13px;
  color: #6c757d;
}

.countdown-text {
  color: #ff4757;
  font-weight: 600;
}

.vote-progress-main {
  margin-bottom: 16px;
}

.vote-results-main {
  display: flex;
  gap: 16px;
  margin-bottom: 8px;
}

.result-item-main {
  display: flex;
  align-items: center;
  gap: 4px;
}

.result-label-main {
  font-size: 13px;
  color: #6c757d;
}

.result-count-main {
  font-size: 14px;
  font-weight: 600;
  padding: 2px 8px;
  border-radius: 12px;
}

.result-count-main.approve {
  background: #d4edda;
  color: #155724;
}

.result-count-main.reject {
  background: #f8d7da;
  color: #721c24;
}

.result-count-main.pending {
  background: #fff3cd;
  color: #856404;
}

.progress-rule-main {
  font-size: 12px;
  color: #6c757d;
}

/* 投票操作按钮 */
.vote-actions-main {
  display: flex;
  flex-direction: column;
  gap: 12px;
}

.vote-buttons-main {
  display: flex;
  gap: 12px;
}

.vote-btn {
  flex: 1;
  padding: 10px 16px;
  border: none;
  border-radius: 6px;
  font-size: 14px;
  font-weight: 500;
  cursor: pointer;
  transition: all 0.3s;
}

.vote-btn.approve-btn {
  background: #28a745;
  color: white;
}

.vote-btn.approve-btn:hover:not(:disabled) {
  background: #218838;
}

.vote-btn.reject-btn {
  background: #dc3545;
  color: white;
}

.vote-btn.reject-btn:hover:not(:disabled) {
  background: #c82333;
}

.vote-btn:disabled {
  opacity: 0.6;
  cursor: not-allowed;
}

/* 候选人选择 */
.candidate-selection-main {
  display: flex;
  flex-direction: column;
  gap: 12px;
}

.candidate-label {
  font-size: 14px;
  font-weight: 500;
  color: #2c3e50;
}

.candidates-list {
  display: flex;
  flex-direction: column;
  gap: 8px;
}

.candidate-item {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 12px;
  background: white;
  border: 2px solid #e9ecef;
  border-radius: 8px;
  cursor: pointer;
  transition: all 0.3s;
}

.candidate-item:hover {
  border-color: #4A90E2;
  background: #f0f6ff;
}

.candidate-item.selected {
  border-color: #4A90E2;
  background: #e3f2fd;
}

.candidate-avatar {
  width: 40px;
  height: 40px;
  border-radius: 50%;
  border: 2px solid #e9ecef;
}

.candidate-name {
  flex: 1;
  font-size: 14px;
  font-weight: 500;
  color: #2c3e50;
}

.selected-icon {
  font-size: 20px;
  color: #4A90E2;
  font-weight: bold;
}

.vote-btn-submit {
  padding: 10px 16px;
  background: #4A90E2;
  color: white;
  border: none;
  border-radius: 6px;
  font-size: 14px;
  font-weight: 500;
  cursor: pointer;
}

.vote-btn-submit:disabled {
  opacity: 0.6;
  cursor: not-allowed;
}

/* 已投票状态 */
.vote-status-main {
  display: flex;
  flex-direction: column;
  gap: 8px;
}

.voted-status-text {
  font-size: 14px;
  color: #28a745;
  font-weight: 500;
}

.withdraw-btn-main {
  padding: 8px 12px;
  background: #ffc107;
  color: #333;
  border: none;
  border-radius: 6px;
  font-size: 12px;
  cursor: pointer;
  width: fit-content;
}

.withdraw-btn-main:disabled {
  opacity: 0.6;
  cursor: not-allowed;
}

/* 投票记录样式 */
.vote-history-section {
  width: calc(100vw - 64px);
  margin: 10px auto;
  background: #fff;
  padding: 16px;
  border-radius: 12px;
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08);
  border: 1px solid rgba(0, 0, 0, 0.05);
}

.history-list {
  display: flex;
  flex-direction: column;
  gap: 16px;
}

.history-item {
  padding: 16px;
  background: #f8f9fa;
  border-radius: 8px;
  border: 1px solid #e9ecef;
}

.history-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-bottom: 12px;
}

.history-title {
  font-size: 15px;
  font-weight: 600;
  color: #2c3e50;
}

.history-status {
  padding: 4px 12px;
  border-radius: 12px;
  font-size: 12px;
  font-weight: 500;
}

.history-status.status-1 {
  background: #d4edda;
  color: #155724;
}

.history-status.status-2 {
  background: #f8d7da;
  color: #721c24;
}

.history-status.status-3 {
  background: #fff3cd;
  color: #856404;
}

.history-status.status-5 {
  background: #e2e3e5;
  color: #383d41;
}

.history-content {
  display: flex;
  flex-direction: column;
  gap: 6px;
  margin-bottom: 12px;
}

.history-info,
.history-time {
  font-size: 13px;
  color: #6c757d;
}

/* 投票详情 */
.history-votes {
  margin-top: 12px;
  padding-top: 12px;
  border-top: 1px solid #e9ecef;
}

.history-votes-title {
  font-size: 14px;
  font-weight: 500;
  color: #2c3e50;
  margin-bottom: 8px;
  display: block;
}

.vote-detail-item {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 8px;
  background: white;
  border-radius: 6px;
  margin-bottom: 6px;
}

.detail-avatar {
  width: 32px;
  height: 32px;
  border-radius: 50%;
  border: 1px solid #e9ecef;
}

.detail-name {
  flex: 1;
  font-size: 13px;
  color: #2c3e50;
}

.detail-choice {
  font-size: 13px;
  font-weight: 500;
  padding: 4px 8px;
  border-radius: 6px;
}

.detail-choice.choice-1 {
  background: #d4edda;
  color: #155724;
}

.detail-choice.choice-2 {
  background: #f8d7da;
  color: #721c24;
}

.detail-choice.choice-3 {
  background: #fff3cd;
  color: #856404;
}

.detail-reason {
  font-size: 12px;
  color: #6c757d;
  margin-left: 8px;
}

.history-result {
  margin-top: 12px;
  padding-top: 12px;
  border-top: 1px solid #e9ecef;
}

.result-summary {
  font-size: 14px;
  color: #2c3e50;
  font-weight: 500;
}
</style>